[GRASS-SVN] r53410 - in grass-addons/grass7: . grass7 grass7/raster grass7/raster/r.agent grass7/raster/r.agent/libagent grass7/raster/r.agent/libold grass7/raster/r.area grass7/raster/r.clump2 grass7/raster/r.convergence grass7/raster/r.convert grass7/raster/r.fuzzy grass7/raster/r.fuzzy/r.fuzzy.logic grass7/raster/r.fuzzy/r.fuzzy.set grass7/raster/r.fuzzy/r.fuzzy.system grass7/raster/r.gdd grass7/raster/r.houghtransform grass7/raster/r.hydrodem grass7/raster/r.in.srtm.region grass7/raster/r.in.wms2 grass7/raster/r.massmov grass7/raster/r.mess grass7/raster/r.modis grass7/raster/r.modis/libmodis grass7/raster/r.modis/r.modis.download grass7/raster/r.modis/r.modis.import grass7/raster/r.regression.multi grass7/raster/r.regression.series grass7/raster/r.stream.basins grass7/raster/r.stream.channel grass7/raster/r.stream.distance grass7/raster/r.stream.extract grass7/raster/r.stream.order grass7/raster/r.stream.segment grass7/raster/r.stream.slope grass7/raster/r.stream.snap grass 7/raster/r.stream.stats grass7/raster/r.sun.angle grass7/raster/r.threshold grass7/raster/r.vol.dem

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Oct 15 11:25:44 PDT 2012


Author: pvanbosgeo
Date: 2012-10-15 11:25:43 -0700 (Mon, 15 Oct 2012)
New Revision: 53410

Added:
   grass-addons/grass7/grass7.txt
   grass-addons/grass7/grass7/
   grass-addons/grass7/grass7/raster.txt
   grass-addons/grass7/grass7/raster/
   grass-addons/grass7/grass7/raster/Makefile
   grass-addons/grass7/grass7/raster/r.agent/
   grass-addons/grass7/grass7/raster/r.agent/libagent/
   grass-addons/grass7/grass7/raster/r.agent/libagent/__init__.py
   grass-addons/grass7/grass7/raster/r.agent/libagent/aco.py
   grass-addons/grass7/grass7/raster/r.agent/libagent/agent.py
   grass-addons/grass7/grass7/raster/r.agent/libagent/ant.py
   grass-addons/grass7/grass7/raster/r.agent/libagent/error.py
   grass-addons/grass7/grass7/raster/r.agent/libagent/playground.py
   grass-addons/grass7/grass7/raster/r.agent/libagent/world.py
   grass-addons/grass7/grass7/raster/r.agent/libold/
   grass-addons/grass7/grass7/raster/r.agent/libold/__init__.py
   grass-addons/grass7/grass7/raster/r.agent/libold/aco.py
   grass-addons/grass7/grass7/raster/r.agent/libold/agent.py
   grass-addons/grass7/grass7/raster/r.agent/libold/alltests.py
   grass-addons/grass7/grass7/raster/r.agent/libold/ant.py
   grass-addons/grass7/grass7/raster/r.agent/libold/error.py
   grass-addons/grass7/grass7/raster/r.agent/libold/layer.py
   grass-addons/grass7/grass7/raster/r.agent/libold/overview.html
   grass-addons/grass7/grass7/raster/r.agent/libold/playground.py
   grass-addons/grass7/grass7/raster/r.agent/libold/rasterlayer.py
   grass-addons/grass7/grass7/raster/r.agent/libold/vectorlayer.py
   grass-addons/grass7/grass7/raster/r.agent/libold/world.py
   grass-addons/grass7/grass7/raster/r.agent/r.agent.aco
   grass-addons/grass7/grass7/raster/r.agent/r.agent.html
   grass-addons/grass7/grass7/raster/r.agent/r.agent.tests.py
   grass-addons/grass7/grass7/raster/r.area/
   grass-addons/grass7/grass7/raster/r.area/Makefile
   grass-addons/grass7/grass7/raster/r.area/main.c
   grass-addons/grass7/grass7/raster/r.area/r.area.html
   grass-addons/grass7/grass7/raster/r.clump2/
   grass-addons/grass7/grass7/raster/r.clump2/Makefile
   grass-addons/grass7/grass7/raster/r.clump2/flag.c
   grass-addons/grass7/grass7/raster/r.clump2/flag.h
   grass-addons/grass7/grass7/raster/r.clump2/local_proto.h
   grass-addons/grass7/grass7/raster/r.clump2/main.c
   grass-addons/grass7/grass7/raster/r.clump2/pq.c
   grass-addons/grass7/grass7/raster/r.clump2/r.clump2.html
   grass-addons/grass7/grass7/raster/r.clump2/ramseg.c
   grass-addons/grass7/grass7/raster/r.clump2/ramseg.h
   grass-addons/grass7/grass7/raster/r.convergence/
   grass-addons/grass7/grass7/raster/r.convergence/Makefile
   grass-addons/grass7/grass7/raster/r.convergence/conv.png
   grass-addons/grass7/grass7/raster/r.convergence/local_proto.h
   grass-addons/grass7/grass7/raster/r.convergence/main.c
   grass-addons/grass7/grass7/raster/r.convergence/memory.c
   grass-addons/grass7/grass7/raster/r.convergence/r.convergence.html
   grass-addons/grass7/grass7/raster/r.convergence/slope_aspect.c
   grass-addons/grass7/grass7/raster/r.convert/
   grass-addons/grass7/grass7/raster/r.convert/r.convert
   grass-addons/grass7/grass7/raster/r.convert/r.convert.all
   grass-addons/grass7/grass7/raster/r.fuzzy/
   grass-addons/grass7/grass7/raster/r.fuzzy/Makefile
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/Makefile
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/local_proto.h
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/logic.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/main.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/r.fuzzy.logic.html
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/Makefile
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/boundary.png
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/fuzzy.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/local_proto.h
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/main.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/r.fuzzy.set.html
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/set.png
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/shape.png
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/Makefile
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/f_result.png
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.map
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.rul
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/fuzzylogic.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/helpers.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/io.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/local_proto.h
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/main.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/map_parser.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/r.fuzzy.system.html
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/rule_parser.c
   grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/system.c
   grass-addons/grass7/grass7/raster/r.gdd/
   grass-addons/grass7/grass7/raster/r.gdd/Makefile
   grass-addons/grass7/grass7/raster/r.gdd/main.c
   grass-addons/grass7/grass7/raster/r.gdd/r.gdd.html
   grass-addons/grass7/grass7/raster/r.houghtransform/
   grass-addons/grass7/grass7/raster/r.houghtransform/Makefile
   grass-addons/grass7/grass7/raster/r.houghtransform/hough.cpp
   grass-addons/grass7/grass7/raster/r.houghtransform/hough.h
   grass-addons/grass7/grass7/raster/r.houghtransform/houghparameters.h
   grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.cpp
   grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.h
   grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.cpp
   grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.h
   grass-addons/grass7/grass7/raster/r.houghtransform/main.cpp
   grass-addons/grass7/grass7/raster/r.houghtransform/matrix.h
   grass-addons/grass7/grass7/raster/r.houghtransform/r.houghtransform.html
   grass-addons/grass7/grass7/raster/r.hydrodem/
   grass-addons/grass7/grass7/raster/r.hydrodem/Makefile
   grass-addons/grass7/grass7/raster/r.hydrodem/bseg.c
   grass-addons/grass7/grass7/raster/r.hydrodem/close.c
   grass-addons/grass7/grass7/raster/r.hydrodem/cseg.c
   grass-addons/grass7/grass7/raster/r.hydrodem/do_astar.c
   grass-addons/grass7/grass7/raster/r.hydrodem/dseg.c
   grass-addons/grass7/grass7/raster/r.hydrodem/flag.h
   grass-addons/grass7/grass7/raster/r.hydrodem/hydro_con.c
   grass-addons/grass7/grass7/raster/r.hydrodem/init_search.c
   grass-addons/grass7/grass7/raster/r.hydrodem/load.c
   grass-addons/grass7/grass7/raster/r.hydrodem/local_proto.h
   grass-addons/grass7/grass7/raster/r.hydrodem/main.c
   grass-addons/grass7/grass7/raster/r.hydrodem/r.hydrodem.html
   grass-addons/grass7/grass7/raster/r.hydrodem/seg.c
   grass-addons/grass7/grass7/raster/r.hydrodem/seg.h
   grass-addons/grass7/grass7/raster/r.in.srtm.region/
   grass-addons/grass7/grass7/raster/r.in.srtm.region/Makefile
   grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.html
   grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.py
   grass-addons/grass7/grass7/raster/r.in.wms2/
   grass-addons/grass7/grass7/raster/r.in.wms2/Makefile
   grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.html
   grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.py
   grass-addons/grass7/grass7/raster/r.in.wms2/wms_base.py
   grass-addons/grass7/grass7/raster/r.in.wms2/wms_drv.py
   grass-addons/grass7/grass7/raster/r.in.wms2/wms_gdal_drv.py
   grass-addons/grass7/grass7/raster/r.massmov/
   grass-addons/grass7/grass7/raster/r.massmov/Makefile
   grass-addons/grass7/grass7/raster/r.massmov/filters.c
   grass-addons/grass7/grass7/raster/r.massmov/filters.h
   grass-addons/grass7/grass7/raster/r.massmov/general_f.c
   grass-addons/grass7/grass7/raster/r.massmov/general_f.h
   grass-addons/grass7/grass7/raster/r.massmov/main.c
   grass-addons/grass7/grass7/raster/r.massmov/r.massmov.html
   grass-addons/grass7/grass7/raster/r.mess/
   grass-addons/grass7/grass7/raster/r.mess/Makefile
   grass-addons/grass7/grass7/raster/r.mess/r.mess
   grass-addons/grass7/grass7/raster/r.mess/r.mess.html
   grass-addons/grass7/grass7/raster/r.modis/
   grass-addons/grass7/grass7/raster/r.modis/Makefile
   grass-addons/grass7/grass7/raster/r.modis/libmodis/
   grass-addons/grass7/grass7/raster/r.modis/libmodis/Makefile
   grass-addons/grass7/grass7/raster/r.modis/libmodis/convertmodis.py
   grass-addons/grass7/grass7/raster/r.modis/libmodis/downmodis.py
   grass-addons/grass7/grass7/raster/r.modis/libmodis/parsemodis.py
   grass-addons/grass7/grass7/raster/r.modis/libmodis/rmodislib.py
   grass-addons/grass7/grass7/raster/r.modis/r.modis.download/
   grass-addons/grass7/grass7/raster/r.modis/r.modis.download/Makefile
   grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.html
   grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.py
   grass-addons/grass7/grass7/raster/r.modis/r.modis.html
   grass-addons/grass7/grass7/raster/r.modis/r.modis.import/
   grass-addons/grass7/grass7/raster/r.modis/r.modis.import/Makefile
   grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.html
   grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.py
   grass-addons/grass7/grass7/raster/r.regression.multi/
   grass-addons/grass7/grass7/raster/r.regression.multi/Makefile
   grass-addons/grass7/grass7/raster/r.regression.multi/main.c
   grass-addons/grass7/grass7/raster/r.regression.multi/r.regression.multi.html
   grass-addons/grass7/grass7/raster/r.regression.series/
   grass-addons/grass7/grass7/raster/r.regression.series/Makefile
   grass-addons/grass7/grass7/raster/r.regression.series/main.c
   grass-addons/grass7/grass7/raster/r.regression.series/r.regression.series.html
   grass-addons/grass7/grass7/raster/r.stream.basins/
   grass-addons/grass7/grass7/raster/r.stream.basins/Makefile
   grass-addons/grass7/grass7/raster/r.stream.basins/basins_fill.c
   grass-addons/grass7/grass7/raster/r.stream.basins/basins_inputs.c
   grass-addons/grass7/grass7/raster/r.stream.basins/io.c
   grass-addons/grass7/grass7/raster/r.stream.basins/io.h
   grass-addons/grass7/grass7/raster/r.stream.basins/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.basins/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.basins/main.c
   grass-addons/grass7/grass7/raster/r.stream.basins/r.stream.basins.html
   grass-addons/grass7/grass7/raster/r.stream.channel/
   grass-addons/grass7/grass7/raster/r.stream.channel/Makefile
   grass-addons/grass7/grass7/raster/r.stream.channel/io.c
   grass-addons/grass7/grass7/raster/r.stream.channel/io.h
   grass-addons/grass7/grass7/raster/r.stream.channel/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.channel/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.channel/main.c
   grass-addons/grass7/grass7/raster/r.stream.channel/r.stream.channel.html
   grass-addons/grass7/grass7/raster/r.stream.channel/stream_topology.c
   grass-addons/grass7/grass7/raster/r.stream.channel/stream_write.c
   grass-addons/grass7/grass7/raster/r.stream.distance/
   grass-addons/grass7/grass7/raster/r.stream.distance/Makefile
   grass-addons/grass7/grass7/raster/r.stream.distance/distance_calc.c
   grass-addons/grass7/grass7/raster/r.stream.distance/distance_init.c
   grass-addons/grass7/grass7/raster/r.stream.distance/io.c
   grass-addons/grass7/grass7/raster/r.stream.distance/io.h
   grass-addons/grass7/grass7/raster/r.stream.distance/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.distance/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.distance/main.c
   grass-addons/grass7/grass7/raster/r.stream.distance/r.stream.distance.html
   grass-addons/grass7/grass7/raster/r.stream.extract/
   grass-addons/grass7/grass7/raster/r.stream.extract/Makefile
   grass-addons/grass7/grass7/raster/r.stream.extract/bseg.c
   grass-addons/grass7/grass7/raster/r.stream.extract/close.c
   grass-addons/grass7/grass7/raster/r.stream.extract/cseg.c
   grass-addons/grass7/grass7/raster/r.stream.extract/del_streams.c
   grass-addons/grass7/grass7/raster/r.stream.extract/do_astar.c
   grass-addons/grass7/grass7/raster/r.stream.extract/dseg.c
   grass-addons/grass7/grass7/raster/r.stream.extract/flag.h
   grass-addons/grass7/grass7/raster/r.stream.extract/init_search.c
   grass-addons/grass7/grass7/raster/r.stream.extract/load.c
   grass-addons/grass7/grass7/raster/r.stream.extract/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.extract/main.c
   grass-addons/grass7/grass7/raster/r.stream.extract/r.stream.extract.html
   grass-addons/grass7/grass7/raster/r.stream.extract/seg.c
   grass-addons/grass7/grass7/raster/r.stream.extract/seg.h
   grass-addons/grass7/grass7/raster/r.stream.extract/streams.c
   grass-addons/grass7/grass7/raster/r.stream.extract/thin.c
   grass-addons/grass7/grass7/raster/r.stream.order/
   grass-addons/grass7/grass7/raster/r.stream.order/Makefile
   grass-addons/grass7/grass7/raster/r.stream.order/io.c
   grass-addons/grass7/grass7/raster/r.stream.order/io.h
   grass-addons/grass7/grass7/raster/r.stream.order/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.order/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.order/main.c
   grass-addons/grass7/grass7/raster/r.stream.order/orders.png
   grass-addons/grass7/grass7/raster/r.stream.order/r.stream.order.html
   grass-addons/grass7/grass7/raster/r.stream.order/stream_init.c
   grass-addons/grass7/grass7/raster/r.stream.order/stream_order.c
   grass-addons/grass7/grass7/raster/r.stream.order/stream_raster_close.c
   grass-addons/grass7/grass7/raster/r.stream.order/stream_topology.c
   grass-addons/grass7/grass7/raster/r.stream.order/stream_vector.c
   grass-addons/grass7/grass7/raster/r.stream.segment/
   grass-addons/grass7/grass7/raster/r.stream.segment/Makefile
   grass-addons/grass7/grass7/raster/r.stream.segment/dirs.png
   grass-addons/grass7/grass7/raster/r.stream.segment/io.c
   grass-addons/grass7/grass7/raster/r.stream.segment/io.h
   grass-addons/grass7/grass7/raster/r.stream.segment/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.segment/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.segment/main.c
   grass-addons/grass7/grass7/raster/r.stream.segment/r.stream.segment.html
   grass-addons/grass7/grass7/raster/r.stream.segment/sectors.png
   grass-addons/grass7/grass7/raster/r.stream.segment/stream_segment.c
   grass-addons/grass7/grass7/raster/r.stream.segment/stream_topology.c
   grass-addons/grass7/grass7/raster/r.stream.segment/stream_vector.c
   grass-addons/grass7/grass7/raster/r.stream.slope/
   grass-addons/grass7/grass7/raster/r.stream.slope/Makefile
   grass-addons/grass7/grass7/raster/r.stream.slope/main.c
   grass-addons/grass7/grass7/raster/r.stream.slope/r.stream.slope.html
   grass-addons/grass7/grass7/raster/r.stream.snap/
   grass-addons/grass7/grass7/raster/r.stream.snap/Makefile
   grass-addons/grass7/grass7/raster/r.stream.snap/io.c
   grass-addons/grass7/grass7/raster/r.stream.snap/io.h
   grass-addons/grass7/grass7/raster/r.stream.snap/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.snap/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.snap/main.c
   grass-addons/grass7/grass7/raster/r.stream.snap/points_io.c
   grass-addons/grass7/grass7/raster/r.stream.snap/r.stream.snap.html
   grass-addons/grass7/grass7/raster/r.stream.snap/snap.c
   grass-addons/grass7/grass7/raster/r.stream.stats/
   grass-addons/grass7/grass7/raster/r.stream.stats/Makefile
   grass-addons/grass7/grass7/raster/r.stream.stats/io.c
   grass-addons/grass7/grass7/raster/r.stream.stats/io.h
   grass-addons/grass7/grass7/raster/r.stream.stats/local_proto.h
   grass-addons/grass7/grass7/raster/r.stream.stats/local_vars.h
   grass-addons/grass7/grass7/raster/r.stream.stats/main.c
   grass-addons/grass7/grass7/raster/r.stream.stats/r.stream.stats.html
   grass-addons/grass7/grass7/raster/r.stream.stats/stats_calculate.c
   grass-addons/grass7/grass7/raster/r.stream.stats/stats_prepare.c
   grass-addons/grass7/grass7/raster/r.stream.stats/stats_print.c
   grass-addons/grass7/grass7/raster/r.sun.angle/
   grass-addons/grass7/grass7/raster/r.sun.angle/Makefile
   grass-addons/grass7/grass7/raster/r.sun.angle/main.c
   grass-addons/grass7/grass7/raster/r.sun.angle/r.sun.angle.html
   grass-addons/grass7/grass7/raster/r.sun.angle/solpos00.c
   grass-addons/grass7/grass7/raster/r.sun.angle/solpos00.h
   grass-addons/grass7/grass7/raster/r.threshold/
   grass-addons/grass7/grass7/raster/r.threshold/Makefile
   grass-addons/grass7/grass7/raster/r.threshold/r.threshold.html
   grass-addons/grass7/grass7/raster/r.threshold/r.threshold.py
   grass-addons/grass7/grass7/raster/r.vol.dem/
   grass-addons/grass7/grass7/raster/r.vol.dem/Makefile
   grass-addons/grass7/grass7/raster/r.vol.dem/chull.c
   grass-addons/grass7/grass7/raster/r.vol.dem/chull.h
   grass-addons/grass7/grass7/raster/r.vol.dem/globals.h
   grass-addons/grass7/grass7/raster/r.vol.dem/macros.h
   grass-addons/grass7/grass7/raster/r.vol.dem/main.c
   grass-addons/grass7/grass7/raster/r.vol.dem/r.vol.dem.html
   grass-addons/grass7/grass7/raster/r.vol.dem/r_vol_dem_layerdown.jpg
   grass-addons/grass7/grass7/raster/r.vol.dem/r_vol_dem_layerup.jpg
Log:


Added: grass-addons/grass7/grass7/raster/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,28 @@
+MODULE_TOPDIR = ..
+
+SUBDIRS = \
+	r.area \
+	r.clump2 \
+	r.convergence \
+	r.fuzzy \
+	r.hydrodem \
+	r.in.srtm.region \
+	r.in.wms2 \
+	r.modis \
+	r.regression.multi \
+	r.regression.series \
+	r.stream.basins \
+	r.stream.channel \
+	r.stream.distance \
+	r.stream.extract \
+	r.stream.order \
+	r.stream.segment \
+	r.stream.slope \
+	r.stream.snap \
+	r.stream.stats \
+	r.threshold
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: subdirs
+

Added: grass-addons/grass7/grass7/raster/r.agent/libagent/__init__.py
===================================================================
Added: grass-addons/grass7/grass7/raster/r.agent/libagent/aco.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libagent/aco.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libagent/aco.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,27 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import error
+import world
+import ant
+
+from math import sqrt
+from math import exp
+from random import randint
+
+class ACO(world.World):
+    """World class for using the Ant Colony Optimization Algorithm for
+       modelling Agent Based worlds."""
+    def __init__(self):
+        world.World.__init__(self, ant.Ant)
+

Added: grass-addons/grass7/grass7/raster/r.agent/libagent/agent.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libagent/agent.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libagent/agent.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,41 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+class Agent(object):
+    """Generic Agent class with limited capabilities, as a basis for
+       child classes."""
+    def __init__(self, timetolive, world, position=[]):
+        self.ttl = timetolive
+        self.world = world
+        self.position = position
+        self.knowscompass = False
+        self.freedom = 0
+    def setposition(self, position):
+        if position and position != []:
+            self.position[0] = position[0]
+            self.position[1] = position[1]
+    def getposition(self):
+        return self.position
+    def move(self, nrofsteps, direction):
+        pass
+    def age(self):
+        if self.ttl > 0:
+            self.ttl -= 1
+            return True
+        else:
+            self.snuffit()
+            return False
+    def snuffit(self):
+        """to die peacefully and without pain."""
+        self.world.kill(self)
+

Added: grass-addons/grass7/grass7/raster/r.agent/libagent/ant.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libagent/ant.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libagent/ant.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,32 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+from random import choice, randint
+import agent
+import error
+
+class Ant(agent.Agent):
+    """Implementation of an Ant Agent for an ACO kind of World."""
+    def __init__(self, timetolive, world, position):
+        agent.Agent.__init__(self, timetolive, world, position)
+        self.position.extend([None,None,0,0])
+        self.home = self.position[:]
+        self.laststeps = [self.position[:]]
+        self.visitedsteps = []
+        self.done = False
+        self.nextstep = [None,None,0,0,0,0]
+        self.goal = []
+        self.penalty = 0.0
+#
+
+

Added: grass-addons/grass7/grass7/raster/r.agent/libagent/error.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libagent/error.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libagent/error.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,43 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+class Error(Exception):
+    """Base class for exceptions in this module.
+
+    Attributes:
+        expr -- Context expression in which the error occurred
+        msg  -- explanation of the error
+    """
+    def __init__(self, expr, msg):
+        self.expr = expr
+        self.msg = msg
+    def __str__(self):
+        return self.expr + " '" + self.msg + "'"
+
+class EnvError(Error):
+    """Exception raised for missing GRASS environement.
+
+    Attributes:
+        expr -- Context expression in which the error occurred
+        msg  -- explanation of the error
+    """
+
+class DataError(Error):
+    """Exception raised for errors in the input.
+
+    Attributes:
+        expr -- Context expression in which the error occurred
+        msg  -- explanation of the error
+    """
+
+

Added: grass-addons/grass7/grass7/raster/r.agent/libagent/playground.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libagent/playground.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libagent/playground.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      very basic test collection for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import grass.script as grass
+
+class Playground(object):
+    """A Playground is a major component of a World, defining
+       and organizing space, and the interface to GRASS."""
+    def __init__(self):
+        self.layers = dict()
+        self.region = grass.region()
+        if self.region['ewres'] != self.region['nsres']:
+            raise error.DataError("r.agent::libagent.playground.Playground()",
+                                    "Only square raster cells make sense.")
+    def getregion(self):
+        return self.region
+    def getbound(self, bound):
+        return self.region[bound]
+    def setlayer(self, layername, layer, force=False):
+        pass
+    def createlayer(self, layername, grassmap=False):
+        pass
+    def getlayer(self, layername):
+        return []
+    def removelayer(self, layername):
+        pass
+    def writelayer(self, layername):
+        pass
+

Added: grass-addons/grass7/grass7/raster/r.agent/libagent/world.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libagent/world.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libagent/world.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,55 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import error
+import playground
+import agent
+
+class World(object):
+    """Generic World class as basis for more complex worlds."""
+    def __init__(self, agenttype=None, pg=None):
+        if pg == None:
+            self.playground = playground.Playground()
+        else:
+            self.playground = pg
+        self.agentclass = agent.Agent
+        if agenttype == None:
+            self.agenttype = self.agentclass
+        else:
+            self.setagenttype(agenttype)
+        self.agents = []
+        self.artefacts = []
+    def addlayertopg(self, layername, layertype):
+        pass
+    def getlayer(self, layername):
+        pass
+#       return layer
+    def rmlayer(self, layername):
+        pass
+    def setagenttype(self, agentype):
+        pass
+    def getagenttype(self):
+        pass
+#       return agenttype
+    def bear(self, timetolive, position, agenttype):
+        pass
+#       return agent
+    def getnextagent():
+        return next(self, agents)
+    def move(self, agent, position):
+        pass
+    def getposition(self, agent):
+        pass
+    def kill(self, agent):
+        pass
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/__init__.py
===================================================================
Added: grass-addons/grass7/grass7/raster/r.agent/libold/aco.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/aco.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/aco.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,228 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by  Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+from math import sqrt
+from math import exp
+from random import randint
+import world
+import error
+import ant
+
+class ACO(world.World):
+    """Ant Colony Optimization Algorithm for Modelling an Agent Based World"""
+    def __init__(self):
+        world.World.__init__(self, ant.Ant)
+        ### auto/constant
+        self.agentclass = ant.Ant
+        self.ants = self.agents
+        self.artefacts.append([])
+        self.holes = self.artefacts[0]
+        self.artefacts.append([])
+        self.sugar = self.artefacts[1]
+        self.surfaceslope = None
+        self.costsurface = None
+        self.pherovapour = None
+        self.bounds = None
+        self.straight = 0
+        self.diagonal = sqrt(2)-1
+        # count paths
+        self.nrop = 0
+        ### user parameter
+        self.globalfreedom = 8
+        self.rounds = 0
+        self.outrounds = 0
+        self.outfilename = ""
+        self.maxpheromone = 2147483647
+        self.minpheromone = 10
+#        self.maxpenalty = 999
+        self.volatilizationtime = 1
+        self.stepintensity = 10
+        self.pathintensity = 10000
+        self.decisionbase = "standard"
+        self.pheroweight = 1
+        self.randomweight = 1
+        self.validposition = "specials"
+# use fibonacci?
+        self.maxants = 100
+        self.antslife = 0
+    def checkvalues(self):
+        if self.costsurface == None:
+            raise error.DataError("aco.ACO.checkvalues()",
+                    "main input missing: costraster")
+        self.playground.setboundsfromlayer("costs")
+        self.playground.forcelayerbounds()
+        self.bounds = self.playground.getrelativebounds()
+        if self.costsurface == None:
+            raise error.DataError("aco.ACO.checkvalues()",
+                    "input layer missing: costsurface")
+        elif self.costsurface == []:
+            if self.surfaceslope == None:
+                raise error.DataError("aco.ACO.checkvalues()",
+                    "input layer missing: please provide cost or slope layer")
+            else:
+                self.calccostsurface()
+        if self.pherovapour == None:
+            raise error.DataError("aco.ACO.checkvalues()",
+                    "output layer missing: pheromoneraster")
+        if self.holes == None:
+            raise error.DataError("aco.ACO.checkvalues()",
+                    "input layer missing: vectorholes")
+        if self.rounds <= 0:
+            raise error.DataError("aco.ACO.checkvalues()",
+                    "number of rounds is zero or not set.")
+        if self.outrounds <= 0:
+            self.outrounds = self.rounds
+        if self.antslife == 0:
+            self.antslife = (self.bounds[4]+self.bounds[5])
+        if self.volatilizationtime > self.rounds:
+            self.volatilizationtime = self.rounds
+        elif self.volatilizationtime < 0:
+            self.volatilizationtime = 0
+        for hole in self.holes[:]:
+            if self.costsurface[hole[0]][hole[1]] < 0:
+                self.holes.remove(hole)
+            else:
+# TODO if two holes are close, choose outermost.. or so.
+                self.pherovapour[hole[0]][hole[1]] = -1
+    def addneighbour(self, positions, position):
+        position[2] = self.costsurface[position[0]][position[1]]
+# TODO > or >=
+#        if position[2] > self.maxpenalty:
+#            return
+        if position[2] >= 0:
+            position[3] = self.pherovapour[position[0]][position[1]]
+            positions.append(position)
+    def calccostsurface(self):
+        for x in range(self.bounds[2]):
+            for y in range(self.bounds[0]):
+                val = self.surfaceslope[x][y]
+                if self.surfaceslope > 0:
+                    self.costsurface[x][y] = (1/exp(-0.035*abs(val+5)))-1
+    def getneighbourpositions(self, position, freedom=None):
+        # position = [ x, y, surfacecost, special/phero, timecost, direction ]
+        if freedom == None:
+            freedom = self.globalfreedom
+        positions = []
+        if freedom >= 4:
+            #north = 1
+#TODO improve with not creating position in any case..
+            p = [position[0], position[1]+1, 0, 0, self.straight, 1]
+            if p[1] <= self.bounds[0]:
+                self.addneighbour(positions, p)
+            #south = 2
+            p = [position[0], position[1]-1, 0, 0, self.straight, 2]
+            if p[1] >= self.bounds[1]:
+                self.addneighbour(positions, p)
+            #east = 3
+            p = [position[0]+1, position[1], 0, 0, self.straight, 3]
+            if p[0] <= self.bounds[2]:
+                self.addneighbour(positions, p)
+            #west = 4
+            p = [position[0]-1, position[1], 0, 0, self.straight, 4]
+            if p[0] >= self.bounds[3]:
+                self.addneighbour(positions, p)
+        if freedom >= 8:
+            #northeast = 5
+            p = [position[0]+1, position[1]+1, 0, 0, self.diagonal, 5]
+            if p[1] <= self.bounds[0] and p[0] <= self.bounds[2]:
+                self.addneighbour(positions, p)
+            #northwest = 6
+            p = [position[0]-1, position[1]+1, 0, 0, self.diagonal, 6]
+            if p[1] <= self.bounds[0] and p[0] >= self.bounds[3]:
+                self.addneighbour(positions, p)
+            #southeast = 7
+            p = [position[0]+1, position[1]-1, 0, 0, self.diagonal, 7]
+            if p[1] >= self.bounds[1] and p[0] <= self.bounds[2]:
+                self.addneighbour(positions, p)
+            #southwest = 8
+            p = [position[0]-1, position[1]-1, 0, 0, self.diagonal, 8]
+            if p[1] >= self.bounds[1] and p[0] >= self.bounds[3]:
+                self.addneighbour(positions, p)
+        return positions
+    def letantsdance(self):
+        if 0 < self.outrounds < self.rounds:
+            mainloops = self.rounds/self.outrounds
+            loops = self.outrounds
+        else:
+            mainloops = 1
+            loops = self.rounds
+        nrofrounds = mainloops*loops
+        remember = loops
+        while mainloops > 0:
+            loops = remember
+            while loops > 0:
+                if len(self.ants) < self.maxants:
+                    position = self.holes[randint(0, len(self.holes)-1)][0:2]
+                    self.bear(None, self.antslife, position)
+                for ant in self.ants:
+                    ant.walk()
+                self.volatilize()
+                loops -= 1
+            self.export(str(mainloops))
+            print "nrofpaths:", self.nrop
+            mainloops -= 1
+        print "nrofrounds", nrofrounds
+    def volatilize(self):
+        if self.volatilizationtime > 0:
+            limit = self.minpheromone
+            halflife = self.volatilizationtime
+            for x in range(self.bounds[2]):
+                for y in range(self.bounds[0]):
+                    if self.pherovapour[x][y] > limit:
+                        val = int(self.pherovapour[x][y]*0.5**(1.0/halflife))
+                        if val > limit:
+                            self.pherovapour[x][y] = val
+    def export(self, suffix=""):
+        layer = self.playground.getlayer("phero")
+        if self.outfilename == "":
+            self.outfilename = layer.outfilename
+        layer.setoutfilename(self.outfilename+suffix)
+        layer.exportfile()
+
+def test(inraster=False, outraster=False, invector=False, slope=False):
+    """Test suite for ACO Class"""
+    print "creating a new ants world.."
+    w = ACO()
+    if inraster:
+        layer = w.importlayer("costs", "raster", inraster)
+        w.costsurface = layer.raster
+    elif slope:
+        layer = w.importlayer("slope", "raster", slope)
+        w.surfaceslope = layer.raster
+        w.playground.setboundsfromlayer("slope")
+        layer = w.createlayer("costs", "raster", None, None)
+        w.costsurface = layer.raster
+        w.calccostsurface()
+    print "start playing with it.."
+    if outraster and invector:
+        layer = w.createlayer("phero", "raster", None, outraster)
+        w.pherovapour = layer.raster
+        layer = w.importlayer("holes", "vector", invector)
+        w.holes = layer.objects
+        w.rounds = 1
+        w.checkvalues()
+        print "set, within:", w.playground.getbounds()
+        print "this translates to:", w.bounds
+        print " this are the holes:"
+        for hole in w.holes:
+            print str(hole)
+        print "neighbourpositions of [9,9]:", w.getneighbourpositions([9,9])
+        print "setting [9,9] to pheromone 999"
+        w.pherovapour[9][9] = 999
+        w.volatilize()
+        print " after some volatilization:",w.pherovapour[9][9]
+        print "playing with some ants"
+        w.letantsdance()
+        print "rock n' roll"
+        w.export()
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/agent.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/agent.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/agent.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,63 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import world
+
+class Agent(object):
+    """standard agent"""
+    def __init__(self, timetolive, world, position=[]):
+        self.ttl = timetolive
+        self.world = world
+        self.position = position
+        self.knowscompass = False
+        self.freedom = 0
+    def setposition(self, position):
+        if position and position != []:
+            self.position[0] = position[0]
+            self.position[1] = position[1]
+    def getposition(self):
+        return self.position
+    def move(self, nrofsteps, direction):
+        pass
+    def age(self):
+        if self.ttl > 0:
+            self.ttl -= 1
+            return True
+        else:
+            self.snuffit()
+            return False
+    def snuffit(self):
+        """to die peacefully and without pain."""
+        self.world.kill(self)
+
+def test():
+    """Test suite for Agent Class"""
+    print "create a world with an agent in."
+    w = world.World(Agent)
+    w.bear(Agent,1,[0,0])
+    print "agent seems fine (for now). time to live:", str(w.agents[0].ttl)
+    print "fake-placing it somewhere ([0,1]).."
+    w.agents[0].setposition([0,1])
+    print "getting its position:", w.agents[0].getposition()
+    print "'cause this takes some time.."
+    w.agents[0].age()
+    print "agent should have grown older by now. time to live:", \
+         str(w.agents[0].ttl)
+    print "and now let agent die.."
+    w.agents[0].age()
+    try:
+        print "should be dead by now. time to live:", str(w.agents[0].ttl)
+    except IndexError:
+        print "IndexError catched: ant was not found in the world anymore."
+    print "all done."
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/alltests.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/alltests.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/alltests.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      very basic test collection for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import sys
+
+import error
+import agent
+import ant
+import layer
+import rasterlayer
+import vectorlayer
+import world
+import aco
+import playground
+
+def dotest(function, argv):
+    while True:
+        n = function.func_doc
+        o = str(argv)
+        if not n:
+            n = str(function)
+        t = str(raw_input("execute this now: '"+n+" - "+o+"'? [y/n/abort] "))
+        if t == "y":
+            if argv != None:
+                function(*argv)
+            else:
+                function()
+            break
+        elif t == "n":
+            break
+        elif t == "abort":
+            exit()
+
+files = ["elev.grid", "elev.grid.out", "arch.vect"]
+
+alltests = [[error.test, None],
+            [agent.test, None],
+            [ant.test, None],
+            [layer.test, [files[2]]],
+            [layer.test, [files[0]]],
+            [rasterlayer.test, [files[0]]],
+            [vectorlayer.test, [files[2]]],
+            [world.test, None],
+            [world.test, files],
+            [aco.test, files],
+            [playground.test, ["raster", files[0], "vector", files[2]]]]
+
+for test in alltests:
+    dotest(test[0], test[1])
+


Property changes on: grass-addons/grass7/grass7/raster/r.agent/libold/alltests.py
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.agent/libold/ant.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/ant.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/ant.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,335 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+from random import choice, randint
+import agent
+import error
+
+class Ant(agent.Agent):
+    """custom"""
+    def __init__(self, timetolive, world, position):
+        agent.Agent.__init__(self, timetolive, world, position)
+        self.position.extend([None,None,0,0])
+        self.home = self.position[:]
+        self.laststeps = [self.position[:]]
+        self.visitedsteps = []
+        self.done = False
+        self.nextstep = [None,None,0,0,0,0]
+        self.goal = []
+        self.penalty = 0.0
+        self.steppaint = world.stepintensity
+        self.pathpaint = world.pathintensity
+        if world.decisionbase == "standard":
+            self.pickaposition = self.smellposition
+            self.pheroweight = self.world.pheroweight * 2
+            self.randomweight = self.world.randomweight * 2
+        elif world.decisionbase == "random":
+            self.pickaposition = self.randomposition
+        elif world.decisionbase == "test":
+            self.pickaposition = self.testposition
+            self.pheroweight = self.world.pheroweight * 2
+            self.randomweight = self.world.randomweight * 2
+        if world.validposition == "avoidloop":
+            self.haspositions = self.avoidloop
+        elif world.validposition == "forgetloop":
+            self.haspositions = self.forgetloop
+        elif world.validposition == "avoidorforgetloop":
+            self.haspositions = self.avoidorforgetloop
+        elif world.validposition == "specials":
+            self.haspositions = self.searchspecials
+    def paint(self, position, value):
+#TODO mv to tests:
+        if self.world.pherovapour[position[0]][position[1]] < 0:
+            print "home:", self.home, "paint:", position, ":", value
+            raise error.Error("Ant.paint()", "Not painting over specials.")
+        if self.world.maxpheromone-value > \
+         self.world.pherovapour[position[0]][position[1]]:
+            self.world.pherovapour[position[0]][position[1]] += value
+    def randomposition(self, positions):
+        self.nextstep = positions[randint(0, len(positions)-1)]
+    def testposition(self, positions):
+        i = 0
+        l = []
+        for pos in positions:
+            l.append([pos[3]/self.randomweight+randint(0,\
+                self.world.maxpheromone)/self.pheroweight, i])
+            i += 1
+        l.sort()
+        self.nextstep = positions[l[0][1]]
+#TODO add some position search alg that avoids high penalties..
+    def smellposition(self, positions):
+        self.nextstep = positions[0]
+        self.nextstep[3] = self.nextstep[3]/self.randomweight+ \
+                    randint(0,self.world.maxpheromone)/self.pheroweight
+        for pos in positions[1:]:
+            pos[3] = pos[3]/self.randomweight+ \
+                    randint(0,self.world.maxpheromone)/self.pheroweight
+            if self.nextstep[3] < pos[3]:
+                self.nextstep = pos
+    def avoidloop(self, positions):
+        ''' This method tries to avoid stepping on already passed
+            nodes. That it is basically. '''
+        # remember all positions for worst case..
+        temppositions = positions[:]
+        for last in self.laststeps[:]:
+            for pos in positions[:]:
+                if last[0] == pos[0] and last[1] == pos[1]:
+                    # position already visited once..
+                    try:
+                        positions.remove(pos)
+                    except ValueError:
+                        pass
+        if len(positions) == 0:
+            # can not be special value, because it would already be visited
+            # make sure it is not home
+            pos = choice(temppositions)
+            if pos[0] == self.home[0] and pos[1] == self.home[1]:
+                temppositions.remove(pos)
+                pos = choice(temppositions)
+            # if none was left: choose another one by chance
+            # no need to proceed with choosing from only one position
+            self.nextstep = pos
+            return True
+        else:
+            for pos in positions[:]:
+                if pos[3] < 0:
+                    # home is already handled because visited
+                    # goal node found. add one to the counter
+                    self.world.nrop += 1
+                    self.done = True
+                    # now, head back home..
+                    self.nextstep = self.laststeps.pop()
+                    return True
+        return False       
+    def avoidorforgetloop(self, positions):
+        ''' This method tries to avoid stepping on already passed
+            nodes. If this is not possible or if a path is coming
+            close to such nodes in the grid, it will grant not to
+            produce loops by deleting all intermediate steps.'''
+        # remember all positions for worst case..
+        temppositions = positions[:]
+        # initially start with no loop found
+        hasposition = False
+        # search for loops, but exclude last step from process (keep it)
+        for last in self.laststeps[:]:
+            if hasposition == True:
+                # remove loop, but remember visited steps
+                self.visitedsteps.append(last)
+                self.laststeps.remove(last)
+            else:
+                # search for loop in positions
+                for pos in positions[:]:
+                    if last[0] == pos[0] and last[1] == pos[1]:
+                        # shortcut found, so remove loop
+                        hasposition = True
+                        # remove that position from possible next ones
+                        positions.remove(pos)
+                        # change direction penalty to new shortcut
+                        self.laststeps[-1][4] = pos[4]
+        # remove all yet visited nodes from possible next positions
+        for visited in self.visitedsteps:
+            for pos in positions[:]:
+                if visited[0] == pos[0] and visited[1] == pos[1]:
+                    # do not step on visited nodes again
+                    positions.remove(pos)
+        if len(positions) == 0:
+            # can not be special value, because it would already be visited
+            # make sure it is not home
+            pos = choice(temppositions)
+            if pos[0] == self.home[0] and pos[1] == self.home[1]:
+                temppositions.remove(pos)
+                pos = choice(temppositions)
+            # if none was left: choose another one by chance
+            # no need to proceed with choosing from only one position
+            self.nextstep = pos
+            return True
+        else:
+            for pos in positions[:]:
+                if pos[3] < 0:
+                    # home is already handled because visited
+                    # goal node found. add one to the counter
+                    self.world.nrop += 1
+                    self.done = True
+                    # now, head back home..
+                    self.nextstep = self.laststeps.pop()
+                    return True
+        return False
+    def forgetloop(self, positions):
+        ''' This method deletes all positions that form a loop in the
+            path. It also prohibits to walk back one step both to the
+            true former position, and to the assumed last step on the
+            newly created shortcut.'''
+        # initially start with no loop found
+        hasposition = False
+        # search for loops, but exclude last step from process (keep it)
+        for last in self.laststeps[:-1]:
+            if hasposition == True:
+                # remove loop
+                self.laststeps.remove(last)
+            else:
+                # search for loop in positions
+                for pos in positions[:]:
+                    if last[0] == pos[0] and last[1] == pos[1]:
+                        # shortcut found, so remove loop
+                        hasposition = True
+                        # remove that position from possible next ones
+                        positions.remove(pos)
+                        # change direction penalty for laststep to new shortcut
+                        self.laststeps[-1][4] = pos[4]
+        for pos in positions[:]:
+            if pos[3] < 0:
+                # promissing, but home is not excluded (only loops are..)
+                if pos[0] == self.home[0] and pos[1] == self.home[1]:
+                    # so, make sure it is not home..
+                    positions.remove(pos)
+                else:
+                    # goal node found. add one to the counter
+                    self.world.nrop += 1
+                    self.done = True
+                    # now, head back home..
+                    self.nextstep = self.laststeps.pop()
+                    return True
+        return False
+    def searchspecials(self, positions):
+        for pos in positions[:]:
+            if pos[3] < 0:
+                # nice value found, goal might be reached
+                if pos[0] == self.home[0] and pos[1] == self.home[1]:
+                    # make sure it is not home..
+                    positions.remove(pos)
+                else:
+                    # this is it! add one to the counter
+                    self.world.nrop += 1
+                    self.done = True
+                    self.nextstep = self.laststeps.pop()
+                    return True
+        return False
+    def choose(self):
+        positions = self.world.getneighbourpositions(self.position)
+        # remove last step from possible neighbourpositions
+        try:
+            positions.remove(self.laststeps[len(self.laststeps)-1])
+        except ValueError:
+            pass
+        if not self.haspositions(positions):
+            self.pickaposition(positions)
+    def walk(self):
+        # we are all only getting older..
+        if self.age() == False:
+            return False
+        # if we do not have decided yet where to go to..
+        if self.nextstep[0] == None:
+            self.choose()
+        # if penalty is positive, wait one round
+        if self.penalty > 0:
+            self.penalty -= 1
+        else:
+            # add penalty from direction or underground
+# TODO: think about adding 1 to each and then multiplicate them ;)
+            self.penalty += self.nextstep[4] + self.nextstep[2]
+            # are we luckily walking home?
+            if self.done == True:
+                # walk back home one step
+                self.position = [self.nextstep[0],self.nextstep[1]]
+                # mark current position as a good choice
+                self.paint(self.position, self.pathpaint)
+                if len(self.laststeps) > 1:
+                    # next step towards back home
+                    self.nextstep = self.laststeps.pop()
+                else:
+                    # retire after work
+                    self.snuffit()
+            else:
+                # make a step
+                self.position = self.nextstep
+                # remember it
+                self.laststeps.append(self.position)
+                # clear nextstep for next round
+                self.nextstep = [None,None,0,0,0,0]
+                # mark current position
+                self.paint(self.position, self.steppaint)
+
+def test():
+    """Test suite for Ant Class"""
+    import aco
+    print "creating a new world"
+    w = aco.ACO()
+    w.bounds = [5,0,5,0,6,6]
+    w.playground.setbounds(5,0,5,0,6,6)
+    print " limits set:",w.playground.getbounds()
+    w.playground.setnewlayer("cost", "raster", True)
+    w.costsurface = w.playground.getlayer("cost").raster
+    w.playground.setnewlayer("phero", "raster", True)
+    w.pherovapour = w.playground.getlayer("phero").raster
+    print " playground looks like (cost+phero)"
+    print " #c#",w.costsurface
+    print " #p#",w.pherovapour
+    w.holes = [[0,0,1]]
+    print ""
+    print "let's put some life in it.."
+    w.bear(Ant,5,[0,0])
+    a = w.agents[0]
+    print " agent seems fine (for now). time to live:",str(a.ttl),\
+        ". location:",a.position
+    a.paint([0,0],500)
+    a.paint([1,1],800)
+    a.paint([1,2],900)
+    print " playground(phero) after some painting:"
+    print " ", w.pherovapour
+    print "look around on positions.."
+    positions = w.getneighbourpositions(a.position)
+    print " tmp positions: ", positions
+    print "- any special cells in raster? ",\
+        a.searchspecials(positions)
+    positions[1][3] = -1
+    print "- any special cells in raster (marking one)? ",\
+        a.searchspecials(positions)
+    print "now die."
+    a.snuffit()
+    print ""
+    print "new ant.."
+    w.bear(Ant,5,[0,0])
+    a = w.agents[0]
+    print " agent seems fine (for now). time to live:",str(a.ttl),\
+        ". location:",a.position
+    print "let's do some positioning..."
+    positions = w.getneighbourpositions(a.position)
+    print "- now pickaposition:"
+    a.randomposition(positions)
+    print " a random choice: ", a.nextstep
+    a.smellposition(positions)
+    print " in smell-mode we would choose: ", a.nextstep
+    a.testposition(positions)
+    print " alternative test:", a.nextstep
+    print "- hasposition alternatives"
+    print " avoid walking in loops:"
+    ps = positions[:]
+    a.avoidloop(ps)
+    print " ",ps
+    ps = positions[:]
+    print " forget loops:"
+    a.forgetloop(ps)
+    print " ",ps
+    ps = positions[:]
+    print " avoid or forget loops:"
+    a.avoidorforgetloop(ps)
+    print " ",ps
+    print "- regularly choose a position now.. based on .. why not: smell."
+    print positions
+    a.choose()
+    print " ant: I'd go there,", a.position
+    print "- make a step forward then.."
+    a.walk()
+    print " ant: I am here now,", a.position
+    print "all done."
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/error.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/error.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/error.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,48 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+class Error(Exception):
+    """Base class for exceptions in this module."""
+    pass
+
+class DataError(Error):
+    """Exception raised for errors in the input.
+
+    Attributes:
+        expr -- Context expression in which the error occurred
+        msg  -- explanation of the error
+    """
+    def __init__(self, expr, msg):
+        self.expr = expr
+        self.msg = msg
+        print "DataError: " + expr + " " + msg
+
+class InputError(Error):
+    """Exception raised for errors in the input.
+
+    Attributes:
+        expr -- input expression in which the error occurred
+        msg  -- explanation of the error
+    """
+    def __init__(self, expr, msg):
+        self.expr = expr
+        self.msg = msg
+        print "InputError: " + expr + " " +msg
+
+def test():
+    """Test suite for Error Class"""
+    try:
+        raise InputError("Error Test Suite", "(no problem with this error)")
+    except InputError:
+        print "catched! all fine."
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/layer.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/layer.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/layer.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,140 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import error
+
+class Layer():
+    """More like a meta/stub Class (or Interface).
+        To be inherited by children."""
+    def __init__(self):
+        self.infilename = None
+        self.outfilename = None
+        self.offset = [None,None]
+        self.limit = [None,None]
+        self.steps = []
+        self.resolution = [1,1]
+        self.fbuffer = None
+    def setinfilename(self, filename):
+        self.infilename = filename
+    def setoutfilename(self, filename):
+        self.outfilename = filename
+    def clearlayer(self):
+        self.offset = [None, None]
+        self.limit = [None, None]
+        if self.steps != []:
+            self.steps = [None, None]
+    def setbounds(self, north, south, east, west, rows=None, cols=None):
+        self.offset = [west,south]
+        self.limit = [east,north]
+        # here layer decides if steps shall be set (see Playground)
+        if self.steps != []:
+            self.steps = [cols,rows]
+            self.resolution[0] = (self.limit[0]-self.offset[0])/self.steps[0]
+            self.resolution[1] = (self.limit[1]-self.offset[1])/self.steps[1]
+    def getbounds(self):
+        if self.steps != []:
+            rows = self.steps[1]
+            cols = self.steps[0]
+        else:
+            rows = None
+            cols = None
+        return [self.limit[1], self.offset[1], self.limit[0],
+                 self.offset[0], rows, cols]
+    def shiftbound(self, direction, delta):
+        if delta < 0:
+            pass
+        elif delta > 0:
+            pass
+    def comparebounds(self, north, south, east, west, rows=None, cols=None):
+        if [west,south] == self.offset and [east,north] == self.limit:
+            if self.steps == []:
+                return True
+            elif [cols,rows] == self.steps:
+                return True
+        return False
+    def forcebounds(self, north, south, east, west, rows=None, cols=None):
+        if not self.comparebounds(north, south, east, west, rows, cols):
+            if self.resolution[0] and self.resolution[1]:
+                xres = self.resolution[0]
+                yres = self.resolution[1]
+            else:
+                xres = 1
+                yres = 1
+            self.shiftbound('north', (north-self.limit[1])/yres)
+            self.shiftbound('south', (south-self.offset[1])/yres)
+            self.shiftbound('east', (east-self.limit[0])/xres)
+            self.shiftbound('west', (west-self.offset[0])/xres)
+            self.setbounds(north, south, east, west, rows, cols)
+    def parsefile(self, fileh):
+        self.fbuffer = fileh.read()
+    def createfile(self, fileh):
+        if self.fbuffer:
+            fileh.write(self.fbuffer)
+    def importfile(self):
+        try:
+            with open(self.infilename, 'r') as fileh:
+                self.parsefile(fileh)
+        except IOError:
+            print "Error: Can not read " + self.infilename
+        except error.InputError:
+            print "Error: " + self.infilename + \
+                    " is not a valid ascii file"
+    def exportfile(self):
+        try:
+            with open(self.outfilename, "w") as fileh:
+                self.createfile(fileh)
+        except IOError:
+            print "Error: Can not write", self.infilename
+
+def test(infile, export=True, remove=True):
+    """Test suite for Layer Class"""
+    outfile = "out-" + infile
+    import os
+    if os.path.isfile(infile) and not os.path.isfile(outfile):
+        l = Layer()
+        print "setting files.."
+        l.setinfilename(infile)
+        l.setoutfilename(outfile)
+        print " import"
+        l.importfile()
+        if export == True:
+            print " export"
+            l.exportfile()
+            import filecmp
+            if filecmp.cmp(infile, outfile):
+                print "import/export seem ok"
+            else:
+                print "import/export failed"
+            if remove == True:
+                os.remove(outfile)
+        print "setting bounds"
+        l.setbounds(9,0,10,1)
+        print " bounds:", str(l.getbounds())
+        print " offset/limit:", str(l.offset), str(l.limit)
+        print "comparing bounds: "
+        print " True:",str(l.comparebounds(*l.getbounds()))
+        print " False:",str(l.comparebounds(l.offset[0]+1,l.offset[1],*l.limit))
+        print "clear all"
+        print "all again with steps:"
+        l.setbounds(9,0,10,1,1,1)
+        print " bounds:", str(l.getbounds())
+        print " offset/limit:", str(l.offset), str(l.limit)
+        print "comparing bounds: "
+        print " True:",str(l.comparebounds(*l.getbounds()))
+        print " False:",str(l.comparebounds(l.offset[0]+1,l.offset[1],*l.limit))
+        print "clear all"
+        l.clearlayer()
+        print " noting: "+str(l.offset)+str(l.limit)
+    else:
+        print "Error: no " + infile + " or " + outfile + " exists."
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/overview.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/overview.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/overview.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,85 @@
+<h2>general oversimplified abstract overview</h2>
+
+<ul><li>world
+<ul><li>e.g. an anthill, or a planet..
+</li><li>organizes how things work together
+</li><li>has:
+<ul><li>playground
+</li><li>list of agents
+<ul><li>killagent(agent)
+</li></ul></li><li>list of artefacts
+</li></ul></li></ul></li><li>aco - world
+<ul><li>is a:
+<ul><li>world
+</li></ul></li><li>for ants as agents with Ant Colony Optimization Algorithm as interaction rule
+</li><li>has:
+<ul><li>playground with
+<ul><li>penalty raster layer
+</li><li>pheromone raster layer
+</li><li>vector layer with holes/anthills
+</li></ul></li><li>list of ants
+</li><li>list of attractors..
+</li><li>list of holes/anthills..
+</li><li>several values that control the behaviour..
+</li></ul></li></ul></li><li>playground
+<ul><li>e.g. dirt, dead wood/leaves/needles, pheromone, etc.
+</li><li>manages layers => coordinates or graph(?)
+</li><li>has:
+<ul><li>layers
+<ul><li>knows its borders
+<ul><li>start/end coordinates
+</li><li>graph ...
+</li></ul></li><li>calcgraph(raster, degreeoffreedom, sizeofstep)
+</li><li>neighbours(node)->listofedges
+</li><li>neighbours(coordinates)->mapofcoordinate=>value's
+</li></ul></li></ul></li></ul></li><li>layer (meta)
+<ul><li>one aspect from playground (one layer therefore..)
+</li></ul></li><li>rasterlayer - layer
+<ul><li>is a:
+<ul><li>layer
+</li></ul></li><li>e.g. pheromone "smell"
+</li><li>represents gis-rasterlayer
+</li><li>has:
+<ul><li>borders
+</li><li>matrix
+</li></ul></li></ul></li><li>vectorlayer - layer
+<ul><li>is a:
+<ul><li>layer
+</li></ul></li><li>e.g. holes in the ground
+</li><li>represents gis-vectorlayer
+</li><li>has:
+<ul><li>borders
+</li><li>list of vector objects/points/..
+</li></ul></li></ul></li><li>graph - layer (not yet available...)
+<ul><li>is a:
+<ul><li>layer
+</li></ul></li><li>made from raster-/vectorlayer
+</li><li>has:
+<ul><li>map of nodes
+<ul><li>node
+<ul><li>id
+</li><li>n:edges list
+</li></ul></li></ul></li><li>list of edges
+<ul><li>edge
+<ul><li>2:nodes
+</li><li>mapof'attribute=value's
+</li></ul></li></ul></li></ul></li></ul></li><li>agent
+<ul><li>e.g. a passenger or an ant
+</li><li>"lives" sort of in the world and on the playground
+</li><li>has:
+<ul><li>ttl
+</li><li>knowscompass
+</li><li>degreeoffreedom - (might be different from playground)
+</li><li>walk()
+</li></ul></li></ul></li><li>ant - agent
+<ul><li>is a:
+<ul><li>agent
+</li></ul></li><li>actor in an aco world
+</li><li>has:
+<ul><li>home position / position of origin / birthplace
+</li><li>list of its positions visited
+</li><li>pheromone intensity to use on certain circumstances
+</li><li>penalty value for its moving velocity
+</li><li>decisionbase for knowing how to find new positions
+</li><li>decisionbase for remembering visited positions
+</li></ul></li></ul></li></ul>

Added: grass-addons/grass7/grass7/raster/r.agent/libold/playground.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/playground.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/playground.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,120 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import rasterlayer
+import vectorlayer
+
+class Playground(object):
+    """..."""
+    def __init__(self):
+        self.layers = dict()
+        self.offset = [None,None]
+        self.limit = [None,None]
+        self.steps = []
+    def setbounds(self, north=None, south=None, east=None, west=None,
+                     rows=None, cols=None):
+        self.offset = [west,south]
+        self.limit = [east,north]
+        # here always try to set steps (see Layer)
+        if rows:
+            self.steps = [cols,rows]
+    def setboundsfromlayer(self, layername):
+        self.setbounds(*self.layers[layername].getbounds())
+    def getbounds(self):
+        if self.steps:
+            rows = self.steps[1]
+            cols = self.steps[0]
+        else:
+            rows = None
+            cols = None
+        return [self.limit[1], self.offset[1], self.limit[0],
+                self.offset[0], rows, cols]
+    def getrelativebounds(self):
+        b = self.getbounds()
+        b = [b[4]-1,0,b[5]-1,0,b[4],b[5]]
+        return b
+    def setlayeralias(self, layername, layer):
+        self.layers[layername] = layer
+    def removelayer(self, layername):
+        del self.layers[layername]
+    def getlayer(self, layername):
+        return self.layers[layername]
+    def setlayer(self, layername, layer, force=False):
+        self.layers[layername] = layer
+        if force and self.offset[0] != None:
+            self.layers[layername].forcebounds(*self.getbounds())
+    def setnewlayer(self, layername, typename, force=False):
+        if typename == "raster":
+            layer = rasterlayer.RasterLayer()
+        elif typename == "vector":
+            layer = vectorlayer.VectorLayer()
+#        elif typename == "graph":
+#            self.layers[layername] = layer.Layer()
+        else:
+            print "layertype not supported (yet)."
+        self.setlayer(layername, layer, force)
+    def setlayerfromfile(self, layername, typename, filename):
+        self.setnewlayer(layername, typename)
+        self.layers[layername].setinfilename(filename)
+        self.layers[layername].importfile()
+        if self.offset[0] != None:
+            self.layers[layername].forcebounds(*self.getbounds())
+    def forcelayerbounds(self):
+        if self.offset[0] != None:
+            for layer in self.layers.itervalues():
+                layer.forcebounds(*self.getbounds())
+
+def test(layer0type=None, layer0=None, layer1type=None, layer1=None):
+    """Test suite for Playground Class"""
+    def testhelper(north=None, south=None, east=None, west=None,
+                     rows=None, cols=None):
+        print " It has this boundaries: "
+        print "  south: " + str(south)
+        print "  west: " + str(west)
+        print "  north: " + str(north)
+        print "  east: " + str(east)
+        print "  rows: " + str(rows)
+        print "  cols: " + str(cols)
+    print "creating new Playground.."
+    pg = Playground()
+    print "start filling it up.."
+    if layer0:
+        pg.setlayerfromfile("l0", layer0type, layer0)
+    else:
+        pg.setbounds(20, 0, 20, 0, 20, 20)
+        pg.setnewlayer("l0", "raster", True)
+        layer0type="raster"
+    print "Layer: "+"l0"+" ("+layer0type+")"
+    testhelper(*pg.layers["l0"].getbounds())
+    if layer1:
+        pg.setlayerfromfile("l1", layer1type, layer1)
+    else:
+        pg.setnewlayer("l1", "vector", True)
+        layer1type="vector"
+    print "Layer: "+"l1"+" ("+layer1type+")"
+    testhelper(*pg.layers["l1"].getbounds())
+    print "Setting global boundaries from layer l0"
+    pg.setboundsfromlayer("l0")
+    testhelper(*pg.getbounds())
+    print "adding new name/alias for l0"
+    pg.setlayeralias("newname", pg.getlayer("l0"))
+    print " " + str(pg.layers.keys())
+    testhelper(*pg.layers["newname"].getbounds())
+    print "remove new name"
+    pg.removelayer("newname")
+    print str(pg.layers.keys())
+    print "force global boundaries on layers"
+    pg.forcelayerbounds()
+    print " l1"
+    testhelper(*pg.layers["l1"].getbounds())
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/rasterlayer.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/rasterlayer.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/rasterlayer.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,254 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import layer
+import error
+
+class RasterLayer(layer.Layer):
+    """..."""
+    def __init__(self):
+        layer.Layer.__init__(self)
+        self.bkeys = ["north", "south", "east", "west", "rows", "cols"]
+        self.steps = [None,None]
+        self.resolution = [None,None]
+        self.raster = []
+        self.gisempty = "*"
+        self.emptyvalue = -1
+    def clearlayer(self):
+        layer.Layer.clearlayer(self)
+        self.raster = []
+    def xyflipmatrix(self, matrix):
+        newmatrix = []
+        for i in range(len(matrix[0])):
+            newrow = []
+            for j in range(len(matrix)):
+                newrow.append(matrix[j][i])
+            newmatrix.append(newrow)
+        return newmatrix
+    def xflipmatrix(self, matrix):
+        raster = []
+        for i in range(len(matrix)-1, -1, -1):
+            raster.append(matrix[i])
+        return raster
+    def shiftbound(self, direction, delta):
+        if delta < 0:
+            if direction == "east":
+                for i in range(delta, 0):
+                    del self.raster[-1]
+            elif direction == "west":
+                for i in range(delta, 0):
+                    self.raster.insert(0,
+                        [0 for i in range(len(self.raster[0]))])
+            elif direction == "north":
+                for i in range(delta, 0):
+                    for j in range(len(self.raster)):
+                        del self.raster[j][-1]
+            elif direction == "south":
+                for i in range(delta, 0):
+                    for j in range(len(self.raster)):
+                        self.raster[j].insert(0, 0)
+        if delta > 0:
+            if direction == "east":
+                for i in range(delta):
+                    self.raster.append([0 for i in range(len(self.raster[0]))])
+            elif direction == "west":
+                for i in range(delta):
+                    del self.raster[0]
+            elif direction == "north":
+                for i in range(delta):
+                    for j in range(len(self.raster)):
+                        self.raster[j].append(0)
+            elif direction == "south":
+                for i in range(delta):
+                    for j in range(len(self.raster)):
+                        del self.raster[j][0]
+    def testresolution(self, north, south, east, west, rows, cols):
+        if rows > 0 < cols:
+            xres = ( east - west ) / cols
+            yres = ( north - south ) / rows
+            if self.resolution[0] == xres and self.resolution[1] == yres:
+                return True
+        return False
+    def forcebounds(self, north, south, east, west, rows, cols):
+        if self.steps[0] == None and self.raster == []:
+            self.setbounds(north, south, east, west, rows, cols)
+            for i in range(cols):
+                self.raster.append([0 for j in range(rows)])
+        elif not self.testresolution(north, south, east, west, rows, cols):
+            raise error.DataError("raster.forcebounds", "wrong resolution")
+        else:
+            layer.Layer.forcebounds(self, north, south, east, west, rows, cols)
+    def parsefile(self, fileh):
+        self.clearlayer()
+        bounds = []
+        for key in self.bkeys:
+            keylength = len(key)
+            line = fileh.readline()
+            if line[0:keylength] in key:
+                bounds.append(int(line[keylength+2:-1]))
+            else:
+                raise error.InputError(self.infilename, "no valid raster")
+        self.setbounds(*bounds)
+        raster = []
+        for line in fileh:
+            rasterline = []
+            for word in line.split(" "):
+                if word.find(".") > 0:
+                    rasterline.append(float(word))
+                elif word.isdigit():
+                    rasterline.append(int(word))
+                elif word in '\r' '\n' '\r\n':
+                    pass
+                else:
+                    rasterline.append(self.emptyvalue)
+            raster.append(rasterline[:])
+        if not (len(raster) == self.steps[1] and
+                        len(raster[0]) == self.steps[0]):
+            raise error.InputError(self.infilename, "wrong # rows/cols")
+        self.raster = self.xyflipmatrix(self.xflipmatrix(raster))
+    def createfile(self, fileh):
+        if self.limit[0]:
+            raster = self.xflipmatrix(self.xyflipmatrix(self.raster))
+            bounds = self.getbounds()
+            bounds.reverse()
+            for key in self.bkeys:
+                line = key + ": " + str(bounds.pop()) + "\n"
+                fileh.writelines(line)
+            for line in raster:
+                for word in line:
+                    if word == self.emptyvalue:
+                        fileh.write(self.gisempty + " ")
+                    else:
+                        fileh.write(str(word) + " ")
+                fileh.write("\n")
+
+def test(infile, export=True, remove=True):
+    """Test suite for RasterLayer Class"""
+    outfile = "out-" + infile
+    import os
+    if os.path.isfile(infile) and not os.path.isfile(outfile):
+        print "create raster layer"
+        r = RasterLayer()
+        r.setinfilename(infile)
+        r.setoutfilename(outfile)
+        print "importing file.."
+        r.importfile()
+        print "file says:"
+        print " r:", str(r.steps[0])+"; c:", str(r.steps[1])
+        print "matrix:"
+        print " x:", str(len(r.raster))+"; y:", str(len(r.raster[0]))
+        if export == True:
+            r.exportfile()
+            import filecmp
+            if filecmp.cmp(infile, outfile):
+                print "import/export seem ok"
+            else:
+                print "import/export failed"
+            if remove == True:
+                os.remove(outfile)
+        print "properties are still:"
+        print " r:", str(r.steps[0])+"; c:", str(r.steps[1])
+        print "flipping raster on x:"
+        b = r.xflipmatrix(r.raster)               
+        print " x:", str(len(b))+"; y:", str(len(b[0]))
+        print "flipping raster on x/y:"
+        b = r.xyflipmatrix(r.raster)
+        print " x:", str(len(b))+"; y:", str(len(b[0]))
+        print "a little resolution test first (to be True):", \
+                str(r.testresolution(*r.getbounds()))
+        print "now force bounds on raster: "
+        print " the same as now"
+        r.forcebounds(*r.getbounds())
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                    str(r.steps)
+        print "  at position [0,0] we have now:", str(r.raster[0][0])
+        print " setting new values now: 100,0,100,0,1,1"
+        r.clearlayer()
+        r.forcebounds(100,0,100,0,1,1)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                    str(r.steps)
+        print "  testing wheter they are set now (True):", \
+                str(r.testresolution(100,0,100,0,1,1))
+        print "  at position [0,0] we have now: ", str(r.raster[0][0])
+        print " momentary raster:"
+        print str(r.raster)
+        print " now reforcing these (correct) values: 200,100,200,100,1,1"
+        r.forcebounds(200,100,200,100,1,1)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                    str(r.steps)
+        print " momentary raster:"
+        print str(r.raster)
+        print " now some wrong values, should throw Error.."
+        try:
+            r.forcebounds(0,0,1,1,1,10000)
+        except error.DataError:
+            print "expected Error received.."
+        print " momentary raster:"
+        print str(r.raster)
+        print " changeing value r[0][0] to 1"
+        r.raster[0][0] = 1
+        print " momentary raster:"
+        print str(r.raster)
+        print "adding some space in the north"
+        print " setting new values now: 400,100,200,100,3,1"
+        r.forcebounds(400,100,200,100,3,1)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print " momentary raster:"
+        print str(r.raster)
+        print "removing some space in the north"
+        print " setting new values now: 300,100,200,100,2,1"
+        r.forcebounds(300,100,200,100,2,1)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print " momentary raster:"
+        print str(r.raster)
+        print "adding some space in the east"
+        r.forcebounds(300,100,400,100,2,3)
+        print " momentary raster:"
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print str(r.raster)
+        print "removing some space in the east"
+        r.forcebounds(300,100,300,100,2,2)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print " momentary raster:"
+        print str(r.raster)
+        print "adding some space in the south"
+        r.forcebounds(300,0,300,100,3,2)
+        print " momentary raster:"
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print str(r.raster)
+        print "removing some space in the south"
+        r.forcebounds(300,100,300,100,2,2)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print " momentary raster:"
+        print str(r.raster)
+        print "adding some space in the west"
+        r.forcebounds(300,100,300,0,2,3)
+        print " momentary raster:"
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print str(r.raster)
+        print "removing some space in the west"
+        r.forcebounds(300,100,300,100,2,2)
+        print "  n/w:", str(r.offset), "s/e:", str(r.limit), "r/c:", \
+                str(r.steps), "::", str(len(r.raster[0]))+":"+str(len(r.raster))
+        print " momentary raster:"
+        print str(r.raster)
+    else:
+        print "Failed: no", infile, "or", outfile, "exists."
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/vectorlayer.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/vectorlayer.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/vectorlayer.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,161 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import layer
+import error
+
+class VectorLayer(layer.Layer):
+    """..."""
+    def __init__(self):
+        layer.Layer.__init__(self)
+        self.objects = []
+        self.gissplit = "|"
+    def clearlayer(self):
+        layer.Layer.clearlayer(self)
+        self.objects = []
+    def shiftbound(self, direction, delta):
+# TODO off by one?
+        for obj in self.objects[:]:
+            if direction == "north":
+                if obj[1] > self.limit[1]+delta:
+                    self.objects.remove(obj)
+            elif direction == "east":
+                if obj[0] > self.limit[0]+delta:
+                    self.objects.remove(obj)
+            elif direction == "south":
+                if obj[1] < self.offset[1]+delta:
+                    self.objects.remove(obj)
+                else:
+                    obj[1] = obj[1]-delta
+            elif direction == "west":
+                if obj[0] < self.offset[0]+delta:
+                    self.objects.remove(obj)
+                else:
+                    obj[0] = obj[0]-delta
+    def reclassify(self, oldres, newres):
+# TODO if nothing changes..?
+# TODO goes to world??
+        dx = (newres[0] + 0.0) / oldres[0]
+        dy = (newres[1] + 0.0) / oldres[1]
+        for obj in self.objects:
+            obj[0] = int(round(obj[0] / dx))
+            obj[1] = int(round(obj[1] / dy))
+    def forcebounds(self, north, south, east, west, norows=None, nocols=None):
+        if self.offset[0] == None or self.offset[0] == self.limit[0]:
+            self.setbounds(north, south, east, west)
+        else:
+            layer.Layer.forcebounds(self, north, south, east, west)
+            if norows != None:
+                newres = [((east-west)/nocols),((north-south)/norows)]
+                self.reclassify(self.resolution, newres)
+                self.resolution = newres
+    def parsefile(self, fileh):
+        self.clearlayer()
+        vectorlist = []
+        self.offset = [0,0]
+        self.limit = [0,0]
+        for line in fileh:
+            if line[-1] in '\r' '\n' '\r\n':
+                line = line[:-1]
+            line = line.split(self.gissplit)
+            avector = []
+            for e in line:
+                avector.append(int(e))
+            vectorlist.append(avector)
+            if avector[0] > int(self.limit[0]):
+                self.limit[0] = avector[0]
+            if avector[1] > int(self.limit[1]):
+                self.limit[1] = avector[1]
+        self.objects = vectorlist
+    def createfile(self, fileh):
+        if self.limit[0] != None:
+            for obj in self.objects:
+                text = ""
+                for element in obj:
+                    if text:
+                        text = text + self.gissplit + str(element)
+                    else:
+                        text = str(element)
+                fileh.write(text + "\n")
+
+def test(infile, export=True, remove=True):
+    """Test suite for VectorLayer Class"""
+    outfile = "out-" + infile
+    import os
+    if os.path.isfile(infile) and not os.path.isfile(outfile):
+        print "create vector layer"
+        v = VectorLayer()
+        v.setinfilename(infile)
+        v.setoutfilename(outfile)
+        print "importing file"
+        v.importfile()
+        print "entries # " + str(len(v.objects))
+        for o in v.objects:
+            print " obj is: x=" + str(o[0]) + " y=" + str(o[1]) + \
+                " cat=" + str(o[2])
+        print "all between:"
+        print " south: " + str(v.offset[1])
+        print " west: " + str(v.offset[0])
+        print " north: " + str(v.limit[1])
+        print " east: " + str(v.limit[0])
+        if export == True:
+            v.exportfile()
+            import filecmp
+            if filecmp.cmp(infile, outfile):
+                print "import/export seem ok"
+            else:
+                print "import/export failed"
+            if remove == True:
+                os.remove(outfile)
+
+        print "creating new example:"
+        print " clear all"
+        v.clearlayer()
+        print " set new values"        
+        print "  setting new boundaries: n9, s0, e9, w0"
+        v.forcebounds( 9, 0, 9, 0 )
+        print "  setting new vectors: 0:5, 5:0, 9:5, 5:9, 5:5"
+        v.objects.append([0, 5, 0])
+        v.objects.append([5, 0, 1])
+        v.objects.append([9, 5, 2])
+        v.objects.append([5, 9, 3])
+        v.objects.append([5, 5, 4])
+        print " set:"
+        print "  south: " + str(v.offset[1])
+        print "  west: " + str(v.offset[0])
+        print "  north: " + str(v.limit[1])
+        print "  east: " + str(v.limit[0])
+        print " entries # " + str(len(v.objects))
+        for o in v.objects:
+            print "  obj is: x=" + str(o[0]) + " y=" + str(o[1]) + " cat=" + \
+                str(o[2])
+        print " set new values"
+        print "  setting new boundaries: n6, s4, e6, w4"
+        v.forcebounds( 6, 4, 6, 4 )
+        print " set:"
+        print "  south: " + str(v.offset[1])
+        print "  west: " + str(v.offset[0])
+        print "  north: " + str(v.limit[1])
+        print "  east: " + str(v.limit[0])
+        print " remaining entries # " + str(len(v.objects))
+        for o in v.objects:             
+            print "  obj is: x=" + str(o[0]) + " y=" + str(o[1]) + " cat=" + \
+                str(o[2])
+        print " again with the old boundaries: n9, s0, e9, w0"
+        v.forcebounds( 9, 0, 9, 0 )
+        for o in v.objects:
+            print "  obj is: x=" + str(o[0]) + " y=" + str(o[1]) + " cat=" + \
+                str(o[2])
+    else:
+        print "Error: no " + infile + " or " + outfile + " exists."
+

Added: grass-addons/grass7/grass7/raster/r.agent/libold/world.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/libold/world.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/libold/world.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,128 @@
+############################################################################
+#
+# MODULE:       r.agent.*
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      library file for the r.agent.* suite
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+import error
+import agent
+import playground
+
+class World(object):
+    """meta class"""
+    def __init__(self, agenttype=None, pg=None):
+        if pg == None:
+            self.playground = playground.Playground()
+        else:
+            self.playground = pg
+        self.agentclass = agent.Agent
+        if agenttype == None:
+            self.agenttype = self.agentclass
+        else:
+            self.setagenttype(agenttype)
+        self.agents = []
+        self.artefacts = []
+    def importlayer(self, name, typename=None, filename=None):
+        if typename != None:
+            self.playground.setlayerfromfile(name, typename, filename)
+        elif filename != None:
+            self.playground.getlayer(name).setinfilename(filename)
+            self.playground.getlayer(name).importfile()
+        else:
+            self.playground.getlayer(name).importfile()
+        return self.playground.getlayer(name)
+    def createlayer(self, name, typename, infile=None, outfile=None):
+        self.playground.setnewlayer(name, typename, False)
+        if infile:
+            self.playground.getlayer(name).setinfilename(infile)
+        if outfile:
+            self.playground.getlayer(name).setoutfilename(outfile)
+        return self.playground.getlayer(name)
+    def exportlayer(self, name, typename=None, filename=None):
+        if filename == None:
+            self.playground.getlayer(name).exportfile()
+        elif typename == None:
+            self.playground.getlayer(name).setoutfilename(filename)
+        else:
+            if not self.playground.getlayer(name):
+                self.playground.setnewlayer(name, typename)
+            self.playground.getlayer(name).setoutfilename(filename)
+            self.playground.getlayer(name).exportfile()
+    def setagenttype(self, agenttype):
+        if issubclass(agenttype, self.agentclass):
+            self.agenttype = agenttype
+    def getagenttype(self):
+        return self.agenttype
+    def bear(self, agenttype=None, timetolife=0, position=[]):
+        if agenttype == None:
+            agenttype = self.agenttype
+        if issubclass(agenttype, self.agentclass):
+            self.agents.append(agenttype(timetolife, self, position))
+    def moveto(self, agent, position):
+        pass
+    def move(self, agent, nrofsteps, direction="random"):
+        pass
+#        print "moving " + self.agent + self.nrofsteps + \
+#            " steps towards " + self.direction
+#    def letwalk(self, agent, nrofsteps=1, direction="random"):
+#        position = agent.getposition()
+#        npositions = self.playground.getneighbourpositions("costs", position)
+        #agent.move()
+    def kill(self, agent):
+        self.agents.remove(agent)
+#    def build(self, artefact):
+#        self.artefacts.add(artefact)
+#    def place(self, artefact, position):
+#        pass
+#    def destroy(self, artefact):
+#        self.artefacts.remove(artefact)
+
+def test(inraster=None, outraster=None, invector=None):
+    """Test suite for World Class"""
+    print "creating world"
+    w = World()
+    print "playing with agents"
+    print " nothing changed.."
+    print "  Agenttype is:", w.getagenttype()
+    print " illegaly overwriting agent.."
+    w.agenttype = ""
+    print "  Agenttype is:", w.getagenttype()
+    print " set new agenttype.."
+    w.setagenttype(agent.Agent)
+    print "  Agenttype is:", w.getagenttype()
+    print "giving birth to some agents"
+    w.bear()
+    w.bear(agent.Agent)
+    print " Agentlist:", w.agents
+    print "killing an agent"
+    w.kill(w.agents[0])
+    print " Agentlist:", w.agents
+#??    w.build()..
+#??    w.moveto()..
+#??    w.move()..
+#??    w.place()..
+#??    w.letwalk()..
+#??    w.destroy()..
+    print "adding layers?"
+    if inraster:
+        print "  adding raster"
+        w.importlayer("raster", "raster", inraster)
+        print "  re-adding again in diffrent way"
+        w.createlayer("raster", "raster", inraster, inraster)
+        w.importlayer("raster")
+        print "  is set."
+        if outraster:
+            w.exportlayer("raster", "raster", outraster)
+            print "  exported to:", str(outraster), "- check and remove.."
+        if invector:
+            print "  adding vectors"
+            w.importlayer("vector", "vector", invector)
+            print "  is set."
+

Added: grass-addons/grass7/grass7/raster/r.agent/r.agent.aco
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/r.agent.aco	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/r.agent.aco	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,269 @@
+#!/usr/bin/env python
+############################################################################
+#
+# MODULE:       r.agent.aco
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      r.agent.aco is used to organize ant-like agents in a raster
+#               based playground. As decribed by the Ant Colony Optimization
+#               algorithm, the ants wander around looking for attractors,
+#               marking their paths if they find any.
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+#%Module
+#% description: Creates a special kind of world, that follows the rules of ACO - with ant-like agents in it.
+#%End
+#%option
+#% key: outputmap
+#% type: string
+#% gisprompt: old,cell,raster
+#% description: Name of pheromone output map
+#% required : yes
+#%end
+#%option
+#% key: inputmap
+#% type: string
+#% gisprompt: old,cell,raster
+#% description: Name of input pheromone raster map (e.g. from prior run)
+#% required : no
+#%end
+#%flag
+#% key: overwrite
+#% description: Allow overwriting existing pheromone maps (e.g. if in == out)
+#%end
+#%flag
+#% key: overwritecosts
+#% description: Overwrite existing cost map (only used with penalty conversion)
+#%end
+#%option
+#% key: costmap
+#% type: string
+#% gisprompt: old,cell,raster
+#% description: Name of penalty resp. cost raster map (note conversion checkbox)
+#% required : yes
+#%end
+#%flag
+#% key: convert
+#% description: Convert cost (slope..) to penalty map (using "tobler", see docu)
+#%end
+#%option
+#% key: sitesmap
+#% type: string
+#% gisprompt: vector
+#% description: Name of sites map, vector data with possible points of origin
+#% required : yes
+#%end
+#%option
+#% key: rounds
+#% type: integer
+#% gisprompt: number
+#% description: Number of iterations/rounds to run
+#% answer: 999
+#% options: 0-999999
+#% required : yes
+#%end
+#%option
+#% key: outrounds
+#% type: integer
+#% gisprompt: number
+#% description: Produce output after running this number of iterations/rounds
+#% options: 0-999999
+#% required : no
+#%end
+#%option
+#% key: highcostlimit
+#% type: integer
+#% gisprompt: number
+#% description: Penalty values above this point an ant considers as illegal
+#% options: 0-<max integer on system would make sense>
+#% required : no
+#%end
+#%option                                                       
+#% key: lowcostlimit
+#% type: integer
+#% gisprompt: number
+#% description: Penalty values below this point an ant considers as illegal
+#% options: <min integer on system would make sense>-0
+#% required : no
+#%end
+#%option
+#% key: maxpheromone
+#% type: integer
+#% gisprompt: number
+#% description: Absolute maximum of pheromone intensity a position may have
+#% options: <minpheromone>-<max integer on system would make sense>
+#% required : no
+#%end
+#%option
+#% key: minpheromone
+#% type: integer
+#% gisprompt: number
+#% description: Absolute minimum of pheromone intensity to leave on playground
+#% options: 0-<maxpheromone>
+#% required : no
+#%end
+#%option
+#% key: volatilizationtime
+#% type: integer
+#% gisprompt: number
+#% description: Half-life for pheromone to volatize (e.g. =rounds)
+#% options: 0-<max integer on system would make sense>
+#% required : no
+#%end
+#%option
+#% key: stepintensity
+#% type: integer
+#% gisprompt: number
+#% description: Pheromone intensity to leave on each step
+#% options: 0-<max integer on system would make sense>
+#% required : no
+#%end
+#%option
+#% key: pathintensity
+#% type: integer
+#% gisprompt: number
+#% description: Pheromone intensity to leave on found paths
+#% options: 0-<max integer on system would make sense>
+#% required : no
+#%end
+#%option
+#% key: maxants
+#% type: integer
+#% gisprompt: number
+#% description: Maximum amount of ants that may live concurrently (x*y)
+#% options: 0-<the bigger the playground, the more space they have>
+#% required : no
+#%end
+#%option
+#% key: antslife
+#% type: integer
+#% gisprompt: number
+#% description: Time to live for an ant (e.g. four times points distance)
+#% options: 0-<max integer on system would make sense>
+#% required : no
+#%end
+#%option
+#% key: decisionalgorithm
+#% type: string
+#% gisprompt: algorithm
+#% description: Algorithm used for walking step
+#% answer: standard
+#% options: standard,random,test
+#% required : yes
+#%end
+#%option
+#% key: validposition
+#% type: string
+#% gisprompt: algorithm
+#% description: Algorithm used for finding and remembering paths
+#% answer: avoidorforgetloop
+#% options: specials,avoidloop,forgetloop,avoidorforgetloop
+#% required : yes
+#%end
+#%option
+#% key: agentfreedom
+#% type: integer
+#% gisprompt: number
+#% description: Number of possible directions the ant can take (4 or 8)
+#% options: 4,8
+#% required : no
+#%end
+#%option
+#% key: pheromoneweight
+#% type: integer
+#% gisprompt: number
+#% description: How is the pheromone value (P) weighted when walking (p*P:r*R:c*C)
+#% answer: 1
+#% options: 0-999
+#% required : yes
+#%end
+#%option
+#% key: randomnessweight
+#% type: integer
+#% gisprompt: number
+#% description: How is the random value (R) weighted when walking (p*P:r*R:c*C)
+#% answer: 1
+#% options: 0-999
+#% required : yes
+#%end
+#%option
+#% key: costweight
+#% type: integer
+#% gisprompt: number
+#% description: How is the penalty value (C) weighted when walking (p*P:r*R:c*C)
+#% answer: 0
+#% options: 0-999
+#% required : yes
+#%end
+
+import sys
+from grass.script import core as grass
+
+from libagent import error, aco
+
+def main():
+    world = aco.ACO()
+
+    layer = world.importlayer("costs", "raster", options['penaltymap'])
+    world.costsurface = layer.raster
+    world.playground.setboundsfromlayer("costs")
+
+    if options['inputmap']:
+        layer = world.importlayer("phero", "raster", options['inputmap'])
+        world.outfilename = options['outputmap']
+    else:
+        layer = world.createlayer("phero", "raster", None, options['outputmap'])
+        world.pherovapour = layer.raster
+
+    layer = world.importlayer("holes", "vector", options['sitesmap'])
+    world.holes = layer.objects
+
+    world.rounds = int(options['rounds'])
+    if options['outrounds']:
+        world.outrounds = int(options['outrounds'])
+    if options['maxpheromone']:
+        world.maxpheromone = int(options['maxpheromone'])
+    if options['minpheromone']:
+        world.minpheromone = int(options['minpheromone'])
+    if options['volatilizationtime']:
+        world.volatilizationtime = int(options['volatilizationtime'])
+    if options['stepintensity']:
+        world.stepintensity = int(options['stepintensity'])
+    if options['pathintensity']:
+        world.pathintensity = int(options['pathintensity'])
+    if options['maxants']:
+        world.maxants = int(options['maxants'])
+    if options['antslife']:
+        world.antslife = int(options['antslife'])
+    if options['decisionalgorithm']:
+        world.decisionbase = str(options['decisionalgorithm'])
+    if options['validposition']:
+        world.validposition = str(options['validposition'])
+    if options['agentfreedom']:
+        world.globalfreedom = int(options['agentfreedom'])
+    if options['pheromoneweight']:
+        world.pheroweight = int(options['pheromoneweight'])
+    if options['randomnessweight']:
+        world.randomweight = int(options['randomnessweight'])
+    if options['costweight']:
+        world.costweight = int(options['costweight'])
+    #if arglist[0] == "stability":
+        #TODO ask silvia..
+    try:
+        world.checkvalues()
+        world.letantsdance()
+        print "FINISH"
+    except error.DataError:
+        print "Failed to parse args.."
+        sys.exit(1)
+
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    main()
+


Property changes on: grass-addons/grass7/grass7/raster/r.agent/r.agent.aco
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.agent/r.agent.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/r.agent.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/r.agent.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,98 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.agent</em> shall provide an inital base for organizing worlds
+with raster playgrounds and agents in.
+<p>
+As this is only a first implementation the encapsulation that grants
+a modular usage is still suffering..
+<p>
+<em>r.agent</em> is written in python for more transparency and
+better extendability.
+<p>
+As a first world example there is an ACO-based environment
+(see <a href="http://en.wikipedia.org/wiki/Ant_colony_optimization_algorithms">Ant Colony Optimization</a>)
+available (in <em>libold</em> see below..).
+<p>
+The basic concept of such an ACO world, is to take some cost surface
+and transform it to a penalty layer - where for human ants for example
+this penalty layer may be expressed by the walking velocity, e.g. calculated
+with the algorithm proposed by
+<a href="http://www.geodyssey.com/papers/tobler93.html">Tobler1993</a>.
+The actors on the playground will wander around on the playground
+using the time for their paths that correspond with the values in the penalty
+grid.
+If they find some attractor, they walk home to the position they
+originated, marking their way with pheromones. While this
+pheromone vanishes over time, the following agents are more likely
+to choose their next steps to a position that smells most.
+<p>
+This first toolset was mainly developed for
+<a href="http://www.topoi.org/group/a-iii-4/">Topoi Project A-III-4</a>,
+with some
+inspirations from previous work conducted at the
+<a href="http://www.unibe.ch/">Uni Bern</a> in 2008.
+
+
+<h2>NOTES</h2>
+
+The state of this software is: "first do it".
+This is work in progress and its structure will probably change quite a lot
+in the future due to a better integration in GRASS and other refactoring.
+<p>
+The refactoring causes <em>r.agent</em> to not work for the moment. The general
+behaviour can be seen by changeing the imports in <em>r.agent.aco</em>
+to the old library <em>libold</em> -- <em>libagent</em> is coming soon.
+<p>
+Unfortunately the colletion is not very well included in GRASS yet.
+At the moment <em>libold</em> only handles ASCII grid and vector in- and
+output data. With a better GRASS integration (arrays) not only will the code
+get lighter but also these drawbacks shall vanish.
+<p>
+ACO works best on dynamic maps -- it constantly tries to improve paths...
+
+
+<h2>EXAMPLE</h2>
+
+A fictive usecase could look something like this
+(note: at the moment the
+in- and output variables with <em>libold</em>, are still ascii-files):
+<p>
+<div class="code"><pre>
+r.agent.aco outputmap=out.map penaltymap=testpenalty.grid \
+  sitesmap=sites.vect rounds=100 outrounds=100 volatilizationtime=5000 \
+  antslife=2000 maxants=400 pathintensity=1000000
+</pre></div>
+<p>
+For running the total test suite on the libraries,
+i.e. to run all the tests that are at the end
+of each python file, use this test collection
+(for certain tests, the following files must exist though:
+ "elev.grid", and "arch.vect"):
+<p>
+<div class="code"><pre>
+user at host:~$ cd /<pathtoaddons>/r.agent/libagent
+
+user at host:libold$ ./alltests.py
+</pre></div>
+
+<h2>TODO</h2>
+
+Integrate it directly within grass.
+<p>
+Improve encapsulation of classes.
+<p>
+Find good parameters, or parameter finding strategies for the ACO part.
+Try to avoid high penalty fields.
+Think about heuristics too.
+<p>
+Implement other ABM scenarios.
+
+<h2>SEE ALSO</h2>
+
+<h2>AUTHORS</h2>
+
+Michael Lustenberger inofix.ch
+
+<p><i>Last changed: $Date: 2011-11-13 16:47:34 +0100 (Sun, 13 Nov 2011) $</i>
+
+

Added: grass-addons/grass7/grass7/raster/r.agent/r.agent.tests.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.agent/r.agent.tests.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.agent/r.agent.tests.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+############################################################################
+#
+# MODULE:       r.agent.aco
+# AUTHOR(S):    michael lustenberger inofix.ch
+# PURPOSE:      r.agent.aco is used to organize ant-like agents in a raster
+#               based playground. As decribed by the Ant Colony Optimization
+#               algorithm, the ants wander around looking for attractors,
+#               marking their paths if they find any.
+# COPYRIGHT:    (C) 2011 by Michael Lustenberger and the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+def dotest(function, argv):
+    """Global wrapper for the individual test suits."""
+    while True:
+        n = function.func_doc
+        o = str(argv)
+        if not n:
+            n = str(function)
+        t = str(raw_input("execute this now: '"+n+" - "+o+"'? [y/n/abort] "))
+        if t == "y":
+            if argv != None:
+                function(*argv)
+            else:
+                function()
+            break
+        elif t == "n":
+            break
+        elif t == "abort":
+            exit()
+
+def testError(expr, msg):
+    """Test suite for Class: Error"""
+    try:
+        raise error.DataError(expr, msg)
+    except error.DataError:
+        print "catched! all fine."
+
+def testPlayground():
+    """Test suite for Class: Playground"""
+    pg = playground.Playground()
+    
+    print(pg.region)
+
+def testWorld():
+    """Test suite for Class: World"""
+    w = world.World()
+
+def testACO():
+    """Test suite for World-Class: ACO"""
+    w = aco.ACO()
+
+def testAgent(ttl):
+    """Test suite for Class: Agent"""
+    w = world.World()
+    w = agent.Agent(ttl, w)
+
+def testAnt(ttl, position):
+    """Test suite for Agent-Class: Ant"""
+    w = world.World()
+    w = ant.Ant(ttl, w, position)
+
+if __name__ == "__main__":
+    """Main method for testing when run as a script."""
+    import sys
+    import os
+
+    from libagent import error
+
+    if os.environ.get("GISBASE") == None:
+        raise error.EnvError("r.agent::TestSuite", "Please run inside GRASS.")
+
+    from libagent import playground
+    from libagent import world
+    from libagent import aco
+    from libagent import agent
+    from libagent import ant
+
+    alltests = {"error":[testError, ["Error Test Suite",
+                     "(this error is good)"]],
+                "playground":[testPlayground, []],
+                "world":[testWorld, []],
+                "aco":[testACO, []],
+                "Agent":[testAgent, [1]],
+                "Ant":[testAnt, [1, []]]}
+
+    if len(sys.argv) == 1:
+        for test,details in alltests.iteritems():
+            dotest(details[0], details[1])
+    else:
+        sys.argv.pop(0)
+        for t in sys.argv:
+            if t in alltests:
+                dotest(*alltests[t])
+            else:
+                print("Test does not exist: ", t)
+
+


Property changes on: grass-addons/grass7/grass7/raster/r.agent/r.agent.tests.py
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.area/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.area/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.area/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,12 @@
+# fix this relative to include/
+# or use absolute path to the GRASS source code
+MODULE_TOPDIR = ../..
+
+PGM = r.area
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.area/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.area/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.area/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,154 @@
+/* ***************************************************************************
+ *
+ * MODULE:       r.area
+ * AUTHOR(S):    Jarek Jasiewicz <jarekj amu.edu.pl>
+ * PURPOSE:      Calculate area of clumped areas. Remove areas smaller than
+ * 							 given treshold.
+ * 
+ * COPYRIGHT:    (C) 1999-2010 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ****************************************************************************
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+int main(int argc, char *argv[])
+{
+
+	struct GModule *module;
+	struct Option *input,
+								*output,
+								*par_treshold;
+	struct Flag *flag_binary;							
+									
+	struct Cell_head cellhd;
+	struct Range range;
+  struct History history;
+
+	char *mapset;
+	int nrows, ncols;
+	int binary, treshold;
+	int row, col;
+	int infd, outfd;
+	CELL *in_buf;
+	CELL *out_buf;
+	CELL c_min, c_max;
+	int *ncells;
+	int i;
+	
+	G_gisinit(argv[0]);
+	
+	input = G_define_standard_option(G_OPT_R_INPUT);
+  input->description = _("Map created with r.clump");
+  
+  output = G_define_standard_option(G_OPT_R_OUTPUT);
+	output->description = _("Map with area size (in cells)");
+	
+	par_treshold = G_define_option();	/* input stream mask file - optional */
+  par_treshold->key = "treshold";
+  par_treshold->type = TYPE_INTEGER;
+  par_treshold->answer = "0";
+  par_treshold->description = _("Remove areas lower than (0 for none):");
+	
+	flag_binary=G_define_flag();
+	flag_binary->key = 'b';
+  flag_binary->description = _("Binary output");
+	
+
+	 	if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+	
+	
+	treshold = atof(par_treshold->answer);
+	binary = (flag_binary->answer != 0);
+	mapset = (char*)G_find_raster2(input->answer, "");
+	
+	  if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), input->answer);
+	
+	infd = Rast_open_old(input->answer, mapset);
+	Rast_get_cellhd(input->answer, mapset, &cellhd);
+
+	
+		if (Rast_map_type(input->answer, mapset) != CELL_TYPE)
+	 G_fatal_error(_("<%s> is not of type CELL, probably not crated with r.clump"), input->answer);
+	 
+	Rast_init_range(&range);
+	Rast_read_range(input->answer,mapset,&range);
+	Rast_get_range_min_max(&range, &c_min, &c_max);
+	
+	in_buf = Rast_allocate_c_buf();
+	
+	nrows = Rast_window_rows();
+	ncols = Rast_window_cols();
+
+	ncells=G_calloc(c_max+1,sizeof(int));
+
+	G_message(_("Reading..."));
+	for (row = 0; row < nrows; row++) {
+		G_percent(row, nrows, 2);
+		Rast_get_row(infd, in_buf, row, CELL_TYPE);
+
+		for (col = 0; col < ncols; col++) {
+				if(!Rast_is_c_null_value(&in_buf[col])) {
+						if(in_buf[col]<c_min || in_buf[col] > c_max)
+					G_fatal_error(_("Value at row %d, col %d out of range: %d"),row,col,in_buf[col]);
+					ncells[in_buf[col]]++;
+				}
+		}
+	} /* end for row */
+	
+		if(treshold) {
+				for (i=1;i<c_max;++i)
+			if(ncells[i]<treshold)
+    ncells[i]=-1;
+		}
+		
+		if(binary) {
+				for (i=1;i<c_max;++i)
+			ncells[i]= ncells[i]<treshold ? -1 : 1;
+		}
+    
+	outfd = Rast_open_new(output->answer, CELL_TYPE);
+	out_buf = Rast_allocate_c_buf();
+
+  G_message(_("Writing..."));
+	for (row = 0; row < nrows; row++) {
+		G_percent(row, nrows, 2);
+				
+	Rast_get_row(infd, in_buf, row, CELL_TYPE);
+		
+		for (col = 0; col < ncols; col++) {
+				if(Rast_is_c_null_value(&in_buf[col]) || ncells[in_buf[col]]==-1)
+						if(binary)
+					out_buf[col]=0;
+						else
+					Rast_set_c_null_value(&out_buf[col],1);
+				else
+			out_buf[col] = ncells[in_buf[col]];
+		}
+		Rast_put_row(outfd, out_buf, CELL_TYPE);
+	} /* end for row */
+  
+  G_free(ncells);
+  G_free(in_buf);
+	Rast_close(infd);
+	G_free(out_buf);
+	Rast_close(outfd);
+
+	Rast_short_history(output->answer, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(output->answer, &history);
+	
+	G_message(_("Done!"));
+	exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.area/r.area.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.area/r.area.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.area/r.area.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,26 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>input</b></dt>
+<dd>Name of input created with r.clump or another cell category map.</dd>
+<dt><b>treshold</b></dt>
+<dd>Remove areas smaller than treshold, set null for removing areas</dd>
+<dt><b>binary</b></dt>
+<dd>Output map has only 0 and 1 values. If treshold is applied small areas are emoved and replaced by 0</dd>
+<dt><b>output</b></dt>
+<dd>Original categories replaced with number of cells for each category. If areas belonging to category are not continuous every area belonging to the same category has the same area value.</dd>
+</dl>
+<h2>DESCRIPTION</h2>
+<p>module can be used to remove, areas smaller than treshold, reclass according areas (similar to r.reclass area, but work in cells, not hectares and allow create more classes)</p>
+
+<h2>SEE ALSO</h2>
+<em>
+<a href="r.clump.html">r.clump</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+<a href="r.reclass.area.html">r.reclass.area</a>
+</em>
+
+
+<h2>AUTHOR</h2>
+Jarek  Jasiewicz
+
+

Added: grass-addons/grass7/grass7/raster/r.clump2/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.clump2
+
+LIBES = $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.clump2/flag.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/flag.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/flag.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,68 @@
+#include <grass/gis.h>
+#include "flag.h"
+
+FLAG *flag_create(int nrows, int ncols)
+{
+    unsigned char *temp;
+    FLAG *new_flag;
+    register int i;
+
+    new_flag = (FLAG *) G_malloc(sizeof(FLAG));
+    new_flag->nrows = nrows;
+    new_flag->ncols = ncols;
+    new_flag->leng = (ncols + 7) / 8;
+    new_flag->array =
+	(unsigned char **)G_malloc(nrows * sizeof(unsigned char *));
+
+    temp =
+	(unsigned char *)G_malloc(nrows * new_flag->leng *
+				  sizeof(unsigned char));
+
+    for (i = 0; i < nrows; i++) {
+	new_flag->array[i] = temp;
+	temp += new_flag->leng;
+    }
+
+    return (new_flag);
+}
+
+int flag_destroy(FLAG * flags)
+{
+    G_free(flags->array[0]);
+    G_free(flags->array);
+    G_free(flags);
+
+    return 0;
+}
+
+int flag_set(FLAG * flags, int row, int col)
+{
+    flags->array[row][col >> 3] |= (1 << (col & 7));
+
+    return 0;
+}
+
+int flag_unset(FLAG * flags, int row, int col)
+{
+    flags->array[row][col >> 3] &= ~(1 << (col & 7));
+
+    return 0;
+}
+
+int flag_get(FLAG * flags, int row, int col)
+{
+    return (flags->array[row][col >> 3] & (1 << (col & 7)));
+}
+
+int flag_clear_all(FLAG * flags)
+{
+    register int r, c;
+
+    for (r = 0; r < flags->nrows; r++) {
+	for (c = 0; c < flags->leng; c++) {
+	    flags->array[r][c] = 0;
+	}
+    }
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.clump2/flag.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/flag.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/flag.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,66 @@
+#ifndef __FLAG_H__
+#define __FLAG_H__
+
+/* flag.[ch] is a set of routines which will set up an array of bits
+ ** that allow the programmer to "flag" cells in a raster map.
+ **
+ ** FLAG *
+ ** flag_create(nrows,ncols)
+ ** int nrows, ncols;
+ **     opens the structure flag.  
+ **     The flag structure will be a two dimensional array of bits the
+ **     size of nrows by ncols.  Will initalize flags to zero (unset).
+ **
+ ** flag_destroy(flags)
+ ** FLAG *flags;
+ **     closes flags and gives the memory back to the system.
+ **
+ ** flag_clear_all(flags)
+ ** FLAG *flags;
+ **     sets all values in flags to zero.
+ **
+ ** flag_unset(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ **     sets the value of (row, col) in flags to zero.
+ **
+ ** flag_set(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ **     will set the value of (row, col) in flags to one.
+ **
+ ** int
+ ** flag_get(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ **     returns the value in flags that is at (row, col).
+ **
+ ** idea by Michael Shapiro
+ ** code by Chuck Ehlschlaeger
+ ** April 03, 1989
+ */
+
+#define FLAG struct _flagsss_
+FLAG {
+    int nrows, ncols, leng;
+    unsigned char **array;
+};
+
+#define FLAG_UNSET(flags,row,col) \
+	(flags)->array[(row)][(col)>>3] &= ~(1<<((col) & 7))
+
+#define FLAG_SET(flags,row,col) \
+	(flags)->array[(row)][(col)>>3] |= (1<<((col) & 7))
+
+#define FLAG_GET(flags,row,col) \
+	(flags)->array[(row)][(col)>>3] & (1<<((col) & 7))
+
+/* flag.c */
+int flag_clear_all(FLAG *);
+FLAG *flag_create(int, int);
+int flag_destroy(FLAG *);
+int flag_get(FLAG *, int, int);
+int flag_set(FLAG *, int, int);
+int flag_unset(FLAG *, int, int);
+
+#endif /* __FLAG_H__ */

Added: grass-addons/grass7/grass7/raster/r.clump2/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,37 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.clump
+ *
+ * AUTHOR(S):    Michael Shapiro - CERL
+ *
+ * PURPOSE:      Recategorizes data in a raster map layer by grouping cells
+ *               that form physically discrete areas into unique categories.
+ *
+ * COPYRIGHT:    (C) 2006 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ***************************************************************************/
+
+#ifndef __LOCAL_PROTO_H__
+#define __LOCAL_PROTO_H__
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include "flag.h"
+#include "ramseg.h"
+
+extern long pqsize;
+extern CELL *clump_id;
+
+/* pq.c */
+int init_pq(long);
+int free_pq(void);
+int add_pnt(long);
+long drop_pnt(void);
+
+
+#endif /* __LOCAL_PROTO_H__ */

Added: grass-addons/grass7/grass7/raster/r.clump2/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,373 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.clump2
+ *
+ * AUTHOR(S):    Markus Metz
+ *
+ * PURPOSE:      Recategorizes data in a raster map layer by grouping cells
+ *		 that form physically discrete areas into unique categories.
+ *
+ * COPYRIGHT:    (C) 2009 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include "local_proto.h"
+#include <grass/glocale.h>
+
+CELL *clump_id;
+long pqsize;
+
+int main(int argc, char *argv[])
+{
+    struct Colors colr;
+    struct Range range;
+    CELL min, max;
+    int in_fd, out_fd;
+    char title[512];
+    char name[GNAME_MAX];
+    struct GModule *module;
+    struct Option *opt_in;
+    struct Option *opt_out;
+    struct Option *opt_title;
+    struct Option *opt_coord;
+    struct Flag *flag_sides;
+    CELL clump_no, *out_buf;
+    struct Cell_head window, cellhd;
+    int nrows, ncols, r, c;
+    long ncells, counter;
+    void *in_ptr, *in_buf;
+    int map_type, in_size;
+    FLAG *inlist;
+    long ramseg;
+    long index, index_nbr;
+    int sides, s, r_nbr, c_nbr, have_seeds = 0, *id_map = NULL;
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+
+    G_gisinit(argv[0]);
+
+    /* Define the different options */
+
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("statistics"));
+    G_add_keyword(_("reclass"));
+    module->description =
+	_("Recategorizes data in a raster map by grouping cells "
+	  "that form physically discrete areas into unique categories.");
+
+    opt_in = G_define_standard_option(G_OPT_R_INPUT);
+
+    opt_out = G_define_standard_option(G_OPT_R_OUTPUT);
+
+    opt_title = G_define_option();
+    opt_title->key = "title";
+    opt_title->type = TYPE_STRING;
+    opt_title->required = NO;
+    opt_title->description = _("Title");
+    
+    opt_coord = G_define_option();
+    opt_coord->key = "coordinate";
+    opt_coord->type = TYPE_STRING;
+    opt_coord->key_desc = "x,y";
+    opt_coord->multiple = YES;
+    opt_coord->description =
+	_("Map grid coordinates of starting points (E,N)");
+
+    flag_sides = G_define_flag();
+    flag_sides->key = 'e';
+    flag_sides->description = _("Ignore diagonal cells");
+
+    /* parse options */
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    in_fd = Rast_open_old(opt_in->answer, "");
+    if (in_fd < 0)
+	G_fatal_error(_("Unable to open raster map <%s>"), opt_in->answer);
+
+    out_fd = Rast_open_c_new(opt_out->answer);
+    if (out_fd < 0)
+	G_fatal_error(_("Unable to create raster map <%s>"), opt_out->answer);
+
+    if (flag_sides->answer)
+	sides = 4;
+    else
+	sides = 8;
+
+    /* some checks */
+    G_get_set_window(&window);
+    Rast_get_cellhd(opt_in->answer, "", &cellhd);
+
+    if (fabs(window.ew_res - cellhd.ew_res) > GRASS_EPSILON ||
+	fabs(window.ns_res - cellhd.ns_res) > GRASS_EPSILON) {
+	G_warning(_("Current region resolution and raster map resolution mismatch!"));
+	G_warning(_("Real clumps may not be presented"));
+	G_warning("ew diff %e", window.ew_res - cellhd.ew_res);
+	G_warning("ns diff %e", window.ns_res - cellhd.ns_res);
+    }
+
+    nrows = window.rows;
+    ncols = window.cols;
+    
+    {
+	long mem;
+	
+	mem = (long) nrows * ncols * sizeof(CELL) + nrows * ((ncols + 7) / 8) * sizeof(unsigned char);
+	
+	if (mem < 1024)
+	    G_verbose_message(_("Will need %ld bytes of memory"), mem);
+	else {
+	    if (mem / 1024 < 1024)
+		G_verbose_message(_("Will need %.2f KB of memory"), (double) mem / 1024);
+	    else {
+		mem /= 1024;
+		if (mem / 1024 < 1024)
+		    G_verbose_message(_("Will need %.2f MB of memory"), (double) mem / 1024);
+		else {
+		    mem /= 1024;
+		    G_verbose_message(_("Will need %.2f GB of memory"), (double) mem / 1024);
+		}
+	    }
+	}
+    }
+
+    if ((double)nrows * ncols > LONG_MAX)
+	G_fatal_error(_("Current region is too large, can't process raster map <%s>"),
+		      opt_in->answer);
+
+    /* allocate space */
+    clump_id =
+	(CELL *) G_malloc(size_array(&ramseg, nrows, ncols) * sizeof(CELL));
+
+    /* read input */
+    map_type = Rast_get_map_type(in_fd);
+    in_size = Rast_cell_size(map_type);
+    in_buf = Rast_allocate_buf(map_type);
+
+    inlist = flag_create(nrows, ncols);
+
+    G_message(_("Loading input map ..."));
+    for (r = 0; r < nrows; r++) {
+	Rast_get_row(in_fd, in_buf, r, map_type);
+	in_ptr = in_buf;
+	G_percent(r, nrows, 2);
+	for (c = 0; c < ncols; c++) {
+	    index = SEG_INDEX(ramseg, r, c);
+	    if (Rast_is_null_value(in_ptr, map_type))
+		clump_id[index] = 0;
+	    else
+		clump_id[index] = 1;
+
+	    FLAG_UNSET(inlist, r, c);
+
+	    in_ptr = G_incr_void_ptr(in_ptr, in_size);
+	}
+    }
+    G_percent(nrows, nrows, 2);
+
+    Rast_close(in_fd);
+    G_free(in_buf);
+
+    ncells = nrows * ncols;
+    counter = 1;
+
+    /* initialize priority queue */
+    init_pq(nrows * ncols * 0.02);
+
+    clump_no = 1;
+    if (opt_coord->answers) {
+	int col, row, i;
+	double east, north;
+	char **answers = opt_coord->answers;
+	struct Cell_head window;
+	
+	/* get start point coordinates */
+	G_message(_("Get start point coordinates ..."));
+
+	G_get_window(&window);
+	
+	for (; *answers != NULL; answers += 2) {
+	    if (!G_scan_easting(*answers, &east, G_projection()))
+		G_fatal_error(_("Illegal x coordinate <%s>"), *answers);
+	    if (*(answers + 1) == NULL)
+		G_fatal_error(_("Missing y corrdinate"));
+	    if (!G_scan_northing(*(answers + 1), &north, G_projection()))
+		G_fatal_error(_("Illegal y coordinate <%s>"), *(answers + 1));
+
+	    if (east < window.west || east > window.east ||
+		north < window.south || north > window.north) {
+		G_warning(_("Warning, ignoring point outside window: %.4f,%.4f"),
+			  east, north);
+		continue;
+	    }
+	    row = (window.north - north) / window.ns_res;
+	    col = (east - window.west) / window.ew_res;
+	    
+	    index = SEG_INDEX(ramseg, row, col);
+	    if (clump_id[index] != 0) {
+		/* add seed points with decreasing clump ID: first point will seed first clump */
+		clump_id[index] = clump_no++;
+		add_pnt(index);
+		FLAG_SET(inlist, row, col);
+		have_seeds = 1;
+	    }
+	}
+
+	id_map = G_malloc(clump_no * sizeof(int));
+	for (i = 0; i < clump_no; i++)
+	    id_map[i] = i;
+
+	if (!have_seeds)
+	    G_fatal_error(_("All start coordinates fall into NULL (nodata) areas"));
+    }
+    else {
+	index = SEG_INDEX(ramseg, 0, 0);
+	if (clump_id[index] != 0)
+	    clump_id[index] = clump_no++;
+	add_pnt(index);
+	FLAG_SET(inlist, 0, 0);
+    }
+
+    /* determine clumps */
+    G_message(_("Determine clumps ..."));
+
+    int perc = -1, lastperc;
+    while (pqsize > 0) {
+	int start_new = 1;
+
+	lastperc = perc;
+	perc = (double) (counter++ / (double)ncells) * 1000000;
+	if (perc > lastperc && perc < 1000000)
+	    G_percent(perc, 1000000, 2);
+
+	index = drop_pnt();
+	seg_index_rc(ramseg, index, &r, &c);
+
+	for (s = 0; s < sides; s++) {
+	    r_nbr = r + nextdr[s];
+	    c_nbr = c + nextdc[s];
+	    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) {
+
+		if ((FLAG_GET(inlist, r_nbr, c_nbr)) == 0) {
+
+		    index_nbr = SEG_INDEX(ramseg, r_nbr, c_nbr);
+
+		    /* not in clump, start new clump */
+		    if (clump_id[index] == 0 && clump_id[index_nbr] != 0) {
+			/* skip other neighbors of same or other clump */
+			if (start_new) {
+			    clump_id[index_nbr] = clump_no++;
+			    add_pnt(index_nbr);
+			    FLAG_SET(inlist, r_nbr, c_nbr);
+			    start_new = 0;
+			}
+		    }
+		    else if (clump_id[index] == 0 && clump_id[index_nbr] == 0) {
+			if (!have_seeds) {
+			    add_pnt(index_nbr);
+			    FLAG_SET(inlist, r_nbr, c_nbr);
+			}
+		    }
+		    else if (clump_id[index] != 0) {
+			if (clump_id[index_nbr] != 0)
+			    clump_id[index_nbr] = clump_id[index];
+
+			if (!have_seeds ||
+			    (have_seeds && clump_id[index_nbr] != 0)) {
+			    add_pnt(index_nbr);
+			    FLAG_SET(inlist, r_nbr, c_nbr);
+			}
+		    }
+		}
+		else if (have_seeds) {
+		    /* safety check */
+		    index_nbr = SEG_INDEX(ramseg, r_nbr, c_nbr);
+		    if (clump_id[index] != clump_id[index_nbr]) {
+			G_warning(_("%d. and %d. start point are in the same clump, ignoring %d. start point"),
+			          clump_id[index], clump_id[index_nbr], clump_id[index_nbr]);
+			id_map[clump_id[index_nbr]] = clump_id[index];
+			clump_id[index_nbr] = clump_id[index];
+		    }
+		}
+	    }
+	}
+    }
+    free_pq();
+
+    if (counter < ncells) {
+	if (!have_seeds)
+	    G_warning("Missed some cells!");
+	else
+	    G_percent(1, 1, 1);
+    }
+    else if ((double) ((double)counter++ / ncells) * 1000000 < 1000000)
+	G_percent(1, 1, 1);
+    
+    if (have_seeds && clump_no > 1) {
+	int i;
+	
+	for (i = 1; i < clump_no; i++) {
+	    if (id_map[i] - id_map[i - 1] > 1)
+		id_map[i] = id_map[i - 1] + 1;
+	}
+    }
+    
+    /* write output */
+    G_message(_("Write output map ..."));
+    out_buf = Rast_allocate_buf(CELL_TYPE);
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+	for (c = 0; c < ncols; c++) {
+	    index = SEG_INDEX(ramseg, r, c);
+	    if (have_seeds) {
+		if ((FLAG_GET(inlist, r, c)) == 0) {
+		    clump_id[index] = 0;
+		}
+		else
+		    clump_id[index] = id_map[clump_id[index]];
+	    }
+	    if (clump_id[index] == 0)
+		Rast_set_c_null_value(&out_buf[c], 1);
+	    else
+		out_buf[c] = clump_id[index];
+
+	}
+	Rast_put_row(out_fd, out_buf, CELL_TYPE);
+    }
+    G_percent(nrows, nrows, 2);
+    G_free(out_buf);
+    Rast_close(out_fd);
+    G_free(clump_id);
+    flag_destroy(inlist);
+    if (id_map)
+	G_free(id_map);
+
+
+    G_debug(1, "Creating support files...");
+
+    /* build title */
+    if (opt_title->answer != NULL)
+	strcpy(title, opt_title->answer);
+    else
+	sprintf(title, "clump of <%s@%s>", name, G_mapset());
+
+    Rast_put_cell_title(opt_out->answer, title);
+    Rast_read_range(opt_out->answer, G_mapset(), &range);
+    Rast_get_range_min_max(&range, &min, &max);
+    Rast_make_random_colors(&colr, min, max);
+    Rast_write_colors(opt_out->answer, G_mapset(), &colr);
+
+    G_done_msg(_("%d clumps."), range.max);
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.clump2/pq.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/pq.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/pq.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,157 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.clump2
+ *
+ * AUTHOR(S):    Markus Metz
+ *
+ * PURPOSE:      Recategorizes data in a raster map layer by grouping cells
+ *		 that form physically discrete areas into unique categories.
+ *
+ * COPYRIGHT:    (C) 2009 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+#define GET_PARENT(c) (int) (((c) - 2) / 3 + 1)
+#define GET_CHILD(p) (int) (((p) * 3) - 1)
+
+static int heap_alloced = 0;
+static long heap_step;
+static long *heap_index;
+
+int cmp_clump(long cid1, long cid2)
+{
+    if (!cid1)
+	return 0;
+    if (!cid2)
+	return 1;
+    return (cid1 < cid2);
+}
+
+int init_pq(long step)
+{
+    pqsize = 0;
+    if (step < 100)
+	step = 100;
+
+    heap_alloced = heap_step = step;
+    heap_index = (long *)G_malloc(heap_alloced * sizeof(long));
+
+    return 0;
+}
+
+int free_pq(void)
+{
+    if (heap_alloced)
+	G_free(heap_index);
+
+    return 0;
+}
+
+long sift_up(long start, long child_pnt)
+{
+    register long parent, child;
+
+    child = start;
+
+    while (child > 1) {
+	parent = GET_PARENT(child);
+
+	/* child is larger */
+	if (cmp_clump(clump_id[child_pnt], clump_id[heap_index[parent]])) {
+	    /* push parent point down */
+	    heap_index[child] = heap_index[parent];
+	    child = parent;
+	}
+	else
+	    /* no more sifting up, found new slot for child */
+	    break;
+    }
+
+    /* put point in new slot */
+    if (child < start) {
+	heap_index[child] = child_pnt;
+    }
+
+    return child;
+}
+
+int add_pnt(long index)
+{
+    pqsize++;
+    if (pqsize >= heap_alloced) {
+	heap_alloced += heap_step;
+	heap_index =
+	    (long *)G_realloc((void *)heap_index,
+			      heap_alloced * sizeof(long));
+    }
+
+    heap_index[pqsize] = index;
+    sift_up(pqsize, index);
+
+    return 0;
+}
+
+long drop_pnt(void)
+{
+    register long parent, child, childr, i;
+    long next_index;
+
+    if (pqsize == 0)
+	return -1;
+
+    next_index = heap_index[1];
+
+    if (pqsize == 1) {
+	pqsize--;
+
+	heap_index[1] = -1;
+
+	return next_index;
+    }
+
+    /* start with root */
+    parent = 1;
+
+    /* sift down: move hole back towards bottom of heap */
+
+    while ((child = GET_CHILD(parent)) <= pqsize) {
+	if (child < pqsize) {
+	    childr = child + 1;
+	    i = child + 3;
+	    /* get largest child */
+	    while (childr < i && childr <= pqsize) {
+		if (cmp_clump(clump_id[heap_index[childr]], 
+		    clump_id[heap_index[child]])) {
+		    child = childr;
+		}
+		childr++;
+	    }
+	}
+
+	/* move hole down */
+	heap_index[parent] = heap_index[child];
+	parent = child;
+    }
+
+    /* hole is in lowest layer, move to heap end */
+    if (parent < pqsize) {
+	heap_index[parent] = heap_index[pqsize];
+
+	/* sift up last swapped point, only necessary if hole moved to heap end */
+	sift_up(parent, heap_index[parent]);
+    }
+
+    /* the actual drop */
+    pqsize--;
+
+    return next_index;
+}

Added: grass-addons/grass7/grass7/raster/r.clump2/r.clump2.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/r.clump2.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/r.clump2.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,49 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.clump2</em> finds all areas of contiguous cell category values in the
+input raster map layer <em>name.</em> It assigns a unique category value
+to each such area ("clump") in the resulting output raster map layer
+<em>name.</em> Optionally <em>r.clump2</em> uses start points and finds
+only those clumps where the start points are falling into.
+
+<h4>Differences to r.clump</h4>
+
+Category distinctions in the input raster map layer are NOT preserved.
+This means that if distinct category values are adjacent, they will be
+clumped together if possible.
+<p>
+Contrary to r.clump, NULL cells are ignored and not clumped.
+<p>
+<em>r.clump2</em> also consideres diagonal cells. <em>r.clump2</em> can
+be forced to consider only edge cells with the <em>e</em> flag, diagonal
+cells are now ignored.
+<p>
+Linear elements (lines that are a single cell wide) are without the
+<em>e</em> flag always clumped together.
+<p> 
+
+
+<h2>NOTES</h2>
+
+A random color table and other support files are
+generated for the <em>output</em> raster map layer.
+
+<h2>SEE ALSO</h2>
+
+<em><a href="r.clump.html">r.clump</a></em><br>
+<em><a href="r.average.html">r.average</a></em><br>
+<em><a href="r.buffer.html">r.buffer</a></em><br>
+<em><a href="r.grow.html">r.grow</a></em><br>
+<em><a href="r.mapcalc.html">r.mapcalc</a></em><br>
+<em><a href="r.mfilter.html">r.mfilter</a></em><br>
+<em><a href="r.neighbors.html">r.neighbors</a></em><br>
+<em><a href="r.to.vect.html">r.to.vect</a></em><br>
+<em><a href="r.reclass.html">r.reclass</a></em><br>
+<em><a href="r.statistics.html">r.statistics</a></em><br>
+<em><a href="r.support.html">r.support</a></em>
+
+<h2>AUTHOR</h2>
+
+Markus Metz
+
+<p><i>Last changed: $Date: 2011-05-09 14:44:59 +0200 (Mon, 09 May 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.clump2/ramseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/ramseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/ramseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include "ramseg.h"
+
+#ifdef LARGE_MAPS
+
+long size_array(long *ramseg, int nrows, int ncols)
+{
+    *ramseg = (long)ncols;
+    
+    return ((long) nrows * ncols);
+}
+
+/* get r, c from seg_index */
+long seg_index_rc(long ramseg, long seg_index, int *r, int *c)
+{
+    *r = seg_index / ramseg;
+    *c = seg_index - *r * ramseg;
+    
+    return 0;
+}
+
+#else
+
+long size_array(long *ramseg, int nrows, int ncols)
+{
+    long size, segs_in_col;
+
+    segs_in_col = ((nrows - 1) >> RAMSEGBITS) + 1;
+    *ramseg = ((ncols - 1) >> RAMSEGBITS) + 1;
+    size = ((((nrows - 1) >> RAMSEGBITS) + 1) << RAMSEGBITS) *
+	((((ncols - 1) >> RAMSEGBITS) + 1) << RAMSEGBITS);
+    size -= ((segs_in_col << RAMSEGBITS) - nrows) << RAMSEGBITS;
+    size -= (*ram_seg << RAMSEGBITS) - ncols;
+    return (size);
+}
+
+/* get r, c from seg_index */
+long seg_index_rc(long ramseg, long seg_index, int *r, int *c)
+{
+    long seg_no, seg_remainder;
+
+    seg_no = seg_index >> DOUBLEBITS;
+    seg_remainder = seg_index - (seg_no << DOUBLEBITS);
+    *r = ((seg_no / ramseg) << RAMSEGBITS) + (seg_remainder >> RAMSEGBITS);
+    *c = ((seg_no - ((*r) >> RAMSEGBITS) * ramseg) << RAMSEGBITS) +
+	seg_remainder - (((*r) & SEGLENLESS) << RAMSEGBITS);
+    return seg_no;
+}
+
+#endif

Added: grass-addons/grass7/grass7/raster/r.clump2/ramseg.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.clump2/ramseg.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.clump2/ramseg.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,27 @@
+#ifndef __RAMSEG_H__
+#define __RAMSEG_H__
+
+
+#define RAMSEG		long
+#define RAMSEGBITS 	4
+#define DOUBLEBITS 	8	/* 2 * ramsegbits       */
+#define SEGLENLESS 	15	/* 2 ^ ramsegbits - 1   */
+
+#define LARGE_MAPS 1
+
+#ifdef LARGE_MAPS
+
+#define SEG_INDEX(s,r,c) (long) ((r) * (s) + (c))
+
+#else
+
+#define SEG_INDEX(s,r,c) (long) \
+   (((((r) >> RAMSEGBITS) * (s) + ((c) >> RAMSEGBITS)) << DOUBLEBITS) \
+    + (((r) & SEGLENLESS) << RAMSEGBITS) + ((c) & SEGLENLESS))
+    
+#endif
+
+long size_array(long *, int, int);
+long seg_index_rc(long, long, int *, int *);
+
+#endif /* __RAMSEG_H__ */

Added: grass-addons/grass7/grass7/raster/r.convergence/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.convergence/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convergence/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.convergence
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.convergence/conv.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/grass7/raster/r.convergence/conv.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/grass7/grass7/raster/r.convergence/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.convergence/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convergence/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,87 @@
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+
+#ifdef MAIN
+#define GLOBAL
+#else
+#define GLOBAL extern
+#endif
+
+/*
+   PI2= PI/2
+   PI4= PI/4
+   M2PI=2*PI
+ */
+#ifndef PI2
+#define PI2 (2*atan(1))
+#endif
+
+#ifndef PI4
+#define PI4 (atan(1))
+#endif
+
+#ifndef PI
+#define PI (4*atan(1))
+#endif
+
+#ifndef M2PI
+#define M2PI (8*atan(1))
+#endif
+
+#ifndef PI2PERCENT
+#define PI2PERCENT (50/atan(1))
+#endif
+
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define DEGREE2RAD(a) ((a)/(180/PI))
+#define RAD2DEGREE(a) ((a)*(180/PI))
+
+
+typedef char *STRING;
+typedef enum
+{
+    m_STANDARD,
+    m_INVERSE,
+    m_POWER,
+    m_SQUARE,
+    m_GENTLE
+} methods;
+
+typedef struct
+{
+    char elevname[150];
+    RASTER_MAP_TYPE raster_type;
+    FCELL **elev;
+    int fd;			/* file descriptor */
+} MAPS;
+
+typedef struct
+{
+    double cat;
+int r, g, b} FCOLORS;
+
+GLOBAL int gradient, f_circular, f_slope, f_method, window_size, radius;
+GLOBAL float *aspect_matrix, *distance_matrix;
+GLOBAL MAPS elevation;
+GLOBAL FCELL **slope;
+GLOBAL FCELL **aspect;
+
+GLOBAL int nrows, ncols;
+GLOBAL double H, V;
+GLOBAL struct Cell_head window;
+
+int open_map(MAPS * rast);
+int create_maps(void);
+int shift_buffers(int row);
+int get_cell(int col, float *buf_row, void *buf, RASTER_MAP_TYPE raster_type);
+int get_slope_aspect(int row);
+int get_distance(int once, int row);
+int create_distance_aspect_matrix(int row);
+float calculate_convergence(int row, int cur_row, int col);
+int free_map(FCELL ** map, int n);

Added: grass-addons/grass7/grass7/raster/r.convergence/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.convergence/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convergence/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,197 @@
+
+/****************************************************************************
+ *
+ * MODULE:			 r.convergence
+ * AUTHOR(S):		Jarek Jasiewicz jarekj amu.edu.pl
+ * 							Original convergence index in SAGA GIS sofware: Olaf Conrad
+ *							 
+ * PURPOSE:			Calculate convergence index (parameter defining the local convergence of the relief)
+*								
+*
+* COPYRIGHT:		 (C) 2002,2010 by the GRASS Development Team
+*
+*								 This program is free software under the GNU General Public
+*								 License (>=v2). Read the file COPYING that comes with GRASS
+*								 for details.
+*
+ *****************************************************************************/
+
+#define MAIN
+#include "local_proto.h"
+
+int main(int argc, char **argv)
+{
+    struct Option *map_dem,
+	*map_slope,
+	*map_aspect, *par_window, *par_method, *par_differnce, *map_output;
+
+    struct History history;
+    struct Colors colors;
+    struct Flag *flag_slope, *flag_circular;
+
+    int out_fd;
+    float tmp;
+    FCELL *out_buf;
+
+    int i, j, n;
+
+    G_gisinit(argv[0]);
+
+    map_dem = G_define_standard_option(G_OPT_R_INPUT);
+    map_dem->description = _("Digital elevation model map");
+
+    map_output = G_define_standard_option(G_OPT_R_OUTPUT);
+    map_output->description = _("Output convergence index map");
+
+    par_window = G_define_option();
+    par_window->key = "window";
+    par_window->type = TYPE_INTEGER;
+    par_window->answer = "3";
+    par_window->required = YES;
+    par_window->description = _("Window size");
+
+    par_method = G_define_option();
+    par_method->key = "weights";
+    par_method->type = TYPE_STRING;
+    par_method->options = "standard,inverse,power,square,gentle";
+    par_method->answer = "standard";
+    par_method->required = YES;
+    par_method->description =
+	_("Method for reducing the impact of the cell due to distance");
+
+    flag_circular = G_define_flag();
+    flag_circular->key = 'c';
+    flag_circular->description = _("Use circular window (default: square)");
+
+    flag_slope = G_define_flag();
+    flag_slope->key = 's';
+    flag_slope->description =
+	_("Add slope convergence (radically slow down calculation time)");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    window_size = atoi(par_window->answer);
+    if (window_size < 3 || window_size % 2 == 0)
+	G_fatal_error(_("Window size must be odd and at least 3"));
+
+    if (!strcmp(par_method->answer, "standard"))
+	f_method = m_STANDARD;
+    else if (!strcmp(par_method->answer, "inverse"))
+	f_method = m_INVERSE;
+    else if (!strcmp(par_method->answer, "power"))
+	f_method = m_POWER;
+    else if (!strcmp(par_method->answer, "square"))
+	f_method = m_SQUARE;
+    else if (!strcmp(par_method->answer, "gentle"))
+	f_method = m_GENTLE;
+
+    f_circular = (flag_circular->answer != 0);
+    f_slope = (flag_slope->answer != 0);
+
+    /* align window */
+    G_check_input_output_name(map_dem->answer, map_output->answer,
+			      G_FATAL_EXIT);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    Rast_get_window(&window);
+    radius = window_size / 2;
+
+
+    {
+	int row, col;
+	int cur_row;
+	int i_row, i_col, j_row, j_col;
+	float contr_aspect;
+	float dir;
+	int n = 0;
+	float *local_aspect;
+	float convergence;
+
+	out_fd = Rast_open_new(map_output->answer, FCELL_TYPE);
+	out_buf = Rast_allocate_buf(FCELL_TYPE);
+
+	strcpy(elevation.elevname, map_dem->answer);
+	open_map(&elevation);
+	create_maps();
+
+	/* create aspect matrix and distance_matrix */
+	create_distance_aspect_matrix(0);
+
+	/* cur_row: current to row in the buffer */
+	/* open_map and create_maps create data for first pass */
+
+
+	for (row = 0; row < nrows; ++row) {
+	    G_percent(row, nrows, 2);
+	    cur_row = (row < radius) ? row :
+		((row >=
+		  nrows - radius) ? window_size - (nrows - row) : radius);
+
+	    if (row < radius || row > nrows - radius) {
+		Rast_set_f_null_value(out_buf, ncols);
+		Rast_put_row(out_fd, out_buf, FCELL_TYPE);
+		continue;
+	    }
+
+	    for (col = 0; col < ncols; ++col) {
+		if (col < radius || col > ncols - radius) {
+		    Rast_set_f_null_value(&out_buf[col], 1);
+		    continue;
+		}
+		out_buf[col] =
+		    PI2PERCENT * calculate_convergence(row, cur_row, col);
+	    }
+
+	    if (row > radius && row < nrows - (radius + 1))
+		shift_buffers(row);
+
+	    Rast_put_row(out_fd, out_buf, FCELL_TYPE);
+
+	}			/* end for row */
+	G_percent(row, nrows, 2);
+    }				/* end block */
+
+    {
+	FCOLORS fcolr[7] = {
+	    {-100, 56, 0, 0}
+	    ,
+	    {-70, 128, 0, 0}
+	    ,
+	    {-50, 255, 0, 0}
+	    ,
+	    {0, 255, 255, 255}
+	    ,
+	    {50, 0, 0, 255}
+	    ,
+	    {70, 0, 0, 128}
+	    ,
+	    {100, 0, 0, 56}
+	};
+
+	Rast_init_colors(&colors);
+	for (i = 0; i < 6; ++i)
+	    Rast_add_d_color_rule(&fcolr[i].cat, fcolr[i].r, fcolr[i].g,
+				  fcolr[i].b, &fcolr[i + 1].cat,
+				  fcolr[i + 1].r, fcolr[i + 1].g,
+				  fcolr[i + 1].b, &colors);
+	Rast_write_colors(map_output->answer, G_mapset(), &colors);
+    }
+
+    free_map(slope, window_size);
+    free_map(aspect, window_size);
+    free_map(elevation.elev, window_size + 1);
+    G_free(distance_matrix);
+    G_free(aspect_matrix);
+    G_free(out_buf);
+    Rast_close(out_fd);
+
+    Rast_short_history(map_output->answer, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(map_output->answer, &history);
+
+
+    G_message("Done!");
+    exit(EXIT_SUCCESS);
+
+}

Added: grass-addons/grass7/grass7/raster/r.convergence/memory.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.convergence/memory.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convergence/memory.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,143 @@
+#include "local_proto.h"
+
+int open_map(MAPS * rast)
+{
+
+    int row, col;
+    int fd;
+    char *mapset;
+    struct Cell_head cellhd;
+    int bufsize;
+    void *tmp_buf;
+
+    mapset = (char *)G_find_raster2(rast->elevname, "");
+
+    if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), rast->elevname);
+
+    rast->fd = Rast_open_old(rast->elevname, mapset);
+    Rast_get_cellhd(rast->elevname, mapset, &cellhd);
+    rast->raster_type = Rast_map_type(rast->elevname, mapset);
+
+    if (window.ew_res < cellhd.ew_res || window.ns_res < cellhd.ns_res)
+	G_fatal_error(_("Region resolution shoudn't be lesser than map %s resolution. Run g.region rast=%s to set proper resolution"),
+		      rast->elevname, rast->elevname);
+
+    tmp_buf = Rast_allocate_buf(rast->raster_type);
+    rast->elev = (FCELL **) G_malloc((window_size + 1) * sizeof(FCELL *));
+
+    for (row = 0; row < window_size + 1; ++row) {
+	rast->elev[row] = Rast_allocate_buf(FCELL_TYPE);
+	Rast_get_row(rast->fd, tmp_buf, row, rast->raster_type);
+	for (col = 0; col < ncols; ++col)
+	    get_cell(col, rast->elev[row], tmp_buf, rast->raster_type);
+    }				/* end elev */
+
+    G_free(tmp_buf);
+    return 0;
+}
+
+int get_cell(int col, float *buf_row, void *buf, RASTER_MAP_TYPE raster_type)
+{
+
+    switch (raster_type) {
+
+    case CELL_TYPE:
+	if (Rast_is_null_value(&((CELL *) buf)[col], CELL_TYPE))
+	    Rast_set_f_null_value(&buf_row[col], 1);
+	else
+	    buf_row[col] = (FCELL) ((CELL *) buf)[col];
+	break;
+
+    case FCELL_TYPE:
+	if (Rast_is_null_value(&((FCELL *) buf)[col], FCELL_TYPE))
+	    Rast_set_f_null_value(&buf_row[col], 1);
+	else
+	    buf_row[col] = (FCELL) ((FCELL *) buf)[col];
+	break;
+
+    case DCELL_TYPE:
+	if (Rast_is_null_value(&((DCELL *) buf)[col], DCELL_TYPE))
+	    Rast_set_f_null_value(&buf_row[col], 1);
+	else
+	    buf_row[col] = (FCELL) ((DCELL *) buf)[col];
+    }
+}
+
+int create_maps(void)
+{
+    int row, col;
+
+    G_begin_distance_calculations();
+    if (G_projection() != PROJECTION_LL)
+	get_distance(1, 0);
+
+    slope = (FCELL **) G_malloc(window_size * sizeof(FCELL *));
+    aspect = (FCELL **) G_malloc(window_size * sizeof(FCELL *));
+    for (row = 0; row < window_size; ++row) {
+
+	if (G_projection() == PROJECTION_LL) {
+	    get_distance(0, row);
+	    create_distance_aspect_matrix(row);
+	}
+
+	slope[row] = Rast_allocate_buf(FCELL_TYPE);
+	aspect[row] = Rast_allocate_buf(FCELL_TYPE);
+	get_slope_aspect(row);
+    }
+}
+
+int shift_buffers(int row)
+{
+    int i;
+    int col;
+    void *tmp_buf;
+    FCELL *tmp_elev_buf, *slope_tmp, *aspect_tmp;
+
+    tmp_buf = Rast_allocate_buf(elevation.raster_type);
+
+    tmp_elev_buf = elevation.elev[0];
+
+    for (i = 1; i < window_size + 1; ++i)
+	elevation.elev[i - 1] = elevation.elev[i];
+
+    elevation.elev[window_size] = tmp_elev_buf;
+    Rast_get_row(elevation.fd, tmp_buf, row + radius + 1,
+		 elevation.raster_type);
+
+    for (col = 0; col < ncols; ++col)
+	get_cell(col, elevation.elev[window_size], tmp_buf,
+		 elevation.raster_type);
+
+    G_free(tmp_buf);
+
+    slope_tmp = slope[0];
+    aspect_tmp = aspect[0];
+
+    for (i = 1; i < window_size; ++i) {
+	slope[i - 1] = slope[i];
+	aspect[i - 1] = aspect[i];
+    }
+
+    slope[window_size - 1] = slope_tmp;
+    aspect[window_size - 1] = aspect_tmp;
+
+    if (G_projection() == PROJECTION_LL) {
+	get_distance(0, row);
+	create_distance_aspect_matrix(row);
+    }
+
+    get_slope_aspect(window_size - 1);
+
+    return 0;
+}
+
+int free_map(FCELL ** map, int n)
+{
+    int i;
+
+    for (i = 0; i < n; ++i)
+	G_free(map[i]);
+    G_free(map);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.convergence/r.convergence.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.convergence/r.convergence.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convergence/r.convergence.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,59 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>-s</b></dt>
+<dd>Increase convergence if slope value is high. Slope parameter radically slow down computation time, especially if window parameter is high. If slope is used addational modifier is used according to formula: sin(current)*sin(target) + cos(current)*cos(target). if slope of current and target cells are equal. The modifier is 1. If not, the modifier is applied with formula: acos(cos(convergence) * modifier)  </dd>
+<dt><b>-c</b></dt>
+<dd>use circular window instead of suqare (default)</dd>
+
+<dt><b>input</b></dt>
+<dd>Digital elevation model. Data can be of any type and any projection. To calculate relief convergnece, r.convergence uses real distance which is recalculated into cell distance, according formula: <br><code>distance_between_current_cell_and_traget_cell/distance_between_current_cell_and_nearest_neighbour_cell.</code> It is important if convergence is calculated for large areas in LatLong projecton.
+</dd>
+
+<dt><b>weights</b></dt>
+<dd>Parameter describing the reduction of the impact of the cell due to its distance, where distance in cells:
+<ul>
+<li><b>standard:</b>no decay
+<li><b>inverse:</b>distance modifier is calculated as 1/x
+<li><b>power:</b>distance modifier is calculated as 1/(x*x)
+<li><b>power:</b>distance modifier is calculated as 1/(x*x)
+<li><b>gentle:</b>distance modifier is calculated as 1/((1-x)/(1+x))
+</ul>
+
+<dt><b>window</b></dt>
+<dd>window size. Must be odd. For now there is no limits in window size. r.convergence uses window size instead of classical radius for compatibility with other GRASS programs.</dd>
+
+
+<dt><b>output</b></dt>
+<dd>Map of convergence index. The values ranges from -100 (max divergent, real peaks and ridges) by 0 (planar areas) to 100 (max convergent, real pits and channels). Classical convergence index presented with degrees (-90 to 90)</dd>
+
+
+<h2>DESCRIPTION</h2>
+<center>
+<h3>How convergence index is calculated (3 x 3 window):<h3>
+<img src=conv.png border=1><br>
+</center>
+Convergence index is a terrain parameter which show the structure od the relief as a set of convergent areas (channels) and divergent areas (ridges). It represents the agreement of aspect direction of surrounding cells with the teoretical matrix direction. Convergence index is mean (or weighted mean if weights are used) aspect difference between real aspect and teoretical maximum divergent direction matrix representing ideal peak (see figure) minus 90 degres. So if there is maximum agreement with divergent matrix the convergence index is (0 - 90) * 10/9 = -100. If there is ideal sink (maximum convergence) the convergence index is (180 -90) * 10/9 = 100.
+Slope and aspect ere calculated internaly with the same formula as in r.slope.aspect
+Convergence index is very useful for analysis of lineamets especially represented by rigdes or chanell systems as well as valley recognition tool.
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.slope.aspect.html">r.slope.aspect</a>,
+<a href="r.param.scale.html">r.param.scale</a>,
+<a href="r.neighbour.html">r.neighbour</a>,
+</em>
+
+
+<h2>REFERENCES</h2>
+<p>
+Claps, P., Fiorentino, M., Oliveto, G., (1994), <i>Informational entropy of fractal river networks</i>,
+Journal of Hydrology, 187(1-2), 145-156 .</p>
+<p>
+Bauer J., Rohdenburg H., Bork H.-R., (1985), Ein Digitales Reliefmodell als Vorraussetzung fuer ein deterministisches Modell der Wasser- und Stoff-Fluesse, <i>IN: Bork, H.-R., Rohdenburg, H., Landschaftsgenese und Landschaftsoekologie, Parameteraufbereitung fuer deterministische Gebiets-Wassermodelle, Grundlagenarbeiten zu Analyse von Agrar-Oekosystemen</i>, 1-15.
+<p>
+Böhner J., Blaschke T., Montanarella, L. (eds.) (2008). SAGA Seconds Out. Hamburger Beiträge zur Physischen Geographie und Landschaftsökologie, 19: 113 s.</p>
+
+<h2>AUTHOR</h2>
+Jarek  Jasiewicz

Added: grass-addons/grass7/grass7/raster/r.convergence/slope_aspect.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.convergence/slope_aspect.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convergence/slope_aspect.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,256 @@
+#include "local_proto.h"
+int get_distance(int once, int row)
+{
+
+    double north, south, east, west, middle;
+    double zfactor = 1;
+
+    if (once) {
+
+	north = Rast_row_to_northing(0.5, &window);
+	middle = Rast_row_to_northing(1.5, &window);
+	south = Rast_row_to_northing(2.5, &window);
+	east = Rast_col_to_easting(2.5, &window);
+	west = Rast_col_to_easting(0.5, &window);
+
+    }
+    else {
+
+	north = Rast_row_to_northing(row + 0.5, &window);
+	middle = Rast_row_to_northing(row + 1.5, &window);
+	south = Rast_row_to_northing(row + 2.5, &window);
+	east = Rast_col_to_easting(2.5, &window);
+	west = Rast_col_to_easting(0.5, &window);
+
+    }
+
+    V = G_distance(east, north, east, south) / zfactor;
+    H = G_distance(east, middle, west, middle) / zfactor;
+    return 0;
+
+}
+
+int create_distance_aspect_matrix(int row)
+{
+
+    int i;
+    int mx, x, my, y;
+    int dx, dy;
+    float distance;
+    int set_to_zero = 0;
+    float cur_northing, cur_easting, target_northing, target_easting;
+    float ns_dist, ew_dist;
+    float min_cell_size;
+
+    aspect_matrix = G_calloc(window_size * window_size, sizeof(float));
+    distance_matrix = G_calloc(window_size * window_size, sizeof(float));
+
+    cur_northing = Rast_row_to_northing(row + 0.5, &window);
+    cur_easting = Rast_col_to_easting(0.5, &window);
+    target_northing = Rast_row_to_northing(row + 1.5, &window);
+    target_easting = Rast_col_to_easting(1.5, &window);
+
+    ns_dist =
+	G_distance(cur_easting, cur_northing, cur_easting, target_northing);
+    ew_dist =
+	G_distance(cur_easting, cur_northing, target_easting, cur_northing);
+
+    min_cell_size = MIN(ns_dist, ew_dist);
+
+    for (my = 0, y = -radius; my < window_size; ++my, ++y)
+	for (mx = 0, x = radius; mx < window_size; ++mx, --x) {
+
+	    cur_northing = Rast_row_to_northing(row + 0.5, &window);
+	    cur_easting = Rast_col_to_easting(0.5, &window);
+	    target_northing = Rast_row_to_northing(row + y + 0.5, &window);
+	    target_easting = Rast_col_to_easting(x + 0.5, &window);
+
+	    distance =
+		G_distance(cur_easting, cur_northing, target_easting,
+			   target_northing);
+	    distance /= min_cell_size;
+
+	    set_to_zero = 0;
+	    if (distance < 1)
+		set_to_zero = 1;
+	    if (f_circular && distance > radius)
+		set_to_zero = 1;
+
+
+	    if (set_to_zero) {
+		distance_matrix[my * window_size + mx] = 0;
+		aspect_matrix[my * window_size + mx] = -1;
+	    }
+	    else {
+		distance_matrix[my * window_size + mx] = distance;
+		ns_dist =
+		    G_distance(cur_easting, cur_northing, cur_easting,
+			       target_northing);
+		ns_dist =
+		    (cur_northing > target_northing) ? ns_dist : -ns_dist;
+		ew_dist =
+		    G_distance(cur_easting, cur_northing, target_easting,
+			       cur_northing);
+		ew_dist = (cur_easting > target_easting) ? -ew_dist : ew_dist;
+
+		aspect_matrix[my * window_size + mx] =
+		    (y != 0.) ? PI + atan2(ew_dist, ns_dist) :
+		    (x > 0. ? PI2 + PI : PI2);
+	    }
+	}
+
+    return 0;
+
+}
+
+int get_slope_aspect(int row)
+{
+
+    int col, i;
+    FCELL c[10];
+    FCELL dx, dy;
+    FCELL *uprow, *thisrow, *downrow;
+    int d_row[] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 };
+    int d_col[] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
+
+    if (row < 1 || row > nrows - 2) {
+	Rast_set_f_null_value(slope[row], ncols);
+	Rast_set_f_null_value(aspect[row], ncols);
+	return 1;
+    }
+
+    Rast_set_f_null_value(&slope[row][0], 1);
+    Rast_set_f_null_value(&aspect[row][0], 1);
+    Rast_set_f_null_value(&slope[row][ncols - 1], 1);
+    Rast_set_f_null_value(&aspect[row][ncols - 1], 1);
+
+    uprow = elevation.elev[row - 1];
+    thisrow = elevation.elev[row];
+    downrow = elevation.elev[row + 1];
+
+    for (col = 1; col < ncols - 1; ++col) {
+
+	for (i = 0; i < 9; ++i)
+	    if (Rast_is_f_null_value
+		(&elevation.elev[row + d_row[i]][col + d_col[i]])) {
+		Rast_set_f_null_value(&slope[row][col], 1);
+		Rast_set_f_null_value(&aspect[row][col], 1);
+		continue;
+	    }
+
+	dx = ((elevation.elev[row - 1][col - 1] +
+	       2 * elevation.elev[row][col - 1] + elevation.elev[row +
+								 1][col -
+								    1]) -
+	      (elevation.elev[row - 1][col + 1] +
+	       2 * elevation.elev[row][col + 1] + elevation.elev[row +
+								 1][col +
+								    1])) /
+	    (H * 4);
+
+	dy = ((elevation.elev[row + 1][col - 1] +
+	       2 * elevation.elev[row + 1][col] + elevation.elev[row +
+								 1][col +
+								    1]) -
+	      (elevation.elev[row - 1][col - 1] +
+	       2 * elevation.elev[row - 1][col] + elevation.elev[row -
+								 1][col +
+								    1])) /
+	    (V * 4);
+
+	slope[row][col] = atan(sqrt(dx * dx + dy * dy));
+	if (dy == 0.)
+	    aspect[row][col] = dx < 0 ? PI + PI2 : PI2;
+	else
+	    aspect[row][col] =
+		atan2(dx, dy) < 0 ? atan2(dx, dy) + M2PI : atan2(dx, dy);
+
+    }
+    return 0;
+}
+
+float calculate_convergence(int row, int cur_row, int col)
+{
+    int i, j, k = 0;
+    float i_distance;
+    float conv, sum = 0, div = 0;
+    float x;
+    float cur_slope;
+    float slope_modifier;
+    float distance_modifier;
+    float cur_northing, cur_easting, target_northing, target_easting,
+	cur_distance;
+
+    if (f_slope) {
+	cur_northing = Rast_row_to_northing(row + 0.5, &window);
+	cur_easting = Rast_col_to_easting(col + 0.5, &window);
+    }
+
+
+    for (i = -radius; i < radius + 1; ++i)
+	for (j = -radius; j < radius + 1; ++j, ++k) {
+
+	    if (cur_row + i < 0 || cur_row + i > window_size - 1 ||
+		col + j < 1 || col + j > ncols - 2)
+		continue;
+	    x = distance_matrix[k];
+
+	    if (x < 1)
+		continue;
+
+	    if (f_slope) {
+		target_northing =
+		    Rast_row_to_northing(row + i + 0.5, &window);
+		target_easting = Rast_col_to_easting(col + j + 0.5, &window);
+
+		cur_distance =
+		    G_distance(cur_easting, cur_northing, target_easting,
+			       target_northing);
+		cur_slope =
+		    (atan
+		     ((elevation.elev[cur_row + i][col + j] -
+		       elevation.elev[cur_row][col]) / cur_distance));
+		slope_modifier =
+		    sin(slope[cur_row][col]) * sin(cur_slope) +
+		    cos(slope[cur_row][col]) * cos(cur_slope);
+	    }
+
+	    conv = aspect[cur_row + i][col + j] - aspect_matrix[k];
+
+	    if (f_slope)
+		conv = acos(slope_modifier * cos(conv));
+
+	    if (conv < -PI)
+		conv += M2PI;
+	    else if (conv > PI)
+		conv -= M2PI;
+
+	    switch (f_method) {
+	    case 0:
+		distance_modifier = 1;
+		break;
+	    case 1:		/* inverse */
+		distance_modifier = x;
+		break;
+	    case 2:		/* power */
+		distance_modifier = x * x;
+		break;
+	    case 3:		/* square */
+		distance_modifier = sqrt(x);
+		break;
+	    case 4:		/* gentle */
+		distance_modifier = 1 + ((1 - x) * (1 + x));
+		break;
+	    default:
+		G_fatal_error(_("Decay: wrong option"));
+	    }
+
+	    sum += fabs(conv) * (1 / distance_modifier);
+	    div += 1 / distance_modifier;
+
+	}			/* end for i, j */
+
+    sum /= div;
+    sum -= PI2;
+    return sum;
+}

Added: grass-addons/grass7/grass7/raster/r.convert/r.convert
===================================================================
--- grass-addons/grass7/grass7/raster/r.convert/r.convert	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convert/r.convert	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,178 @@
+#!/bin/sh
+############################################################################
+#
+# MODULE:       r.convert
+# AUTHOR:       M. Hamish Bowman, Dunedin, New Zealand
+#
+# PURPOSE:      Converts a GRASS 4-6 raster map to a GRASS 7 raster map
+#		  *** EXPERIMENTAL GRASS 7 RASTER DIR FILE LAYOUT ***
+#
+# COPYRIGHT:    (c) 2007 Hamish Bowman, and the GRASS Development Team
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+#%Module
+#% description: Converts a GRASS 4-6 raster map to a GRASS 7 raster map format
+#% keywords: raster, import, conversion
+#%end
+#%option
+#% key: map
+#% type: string
+#% gisprompt: old,cell,raster
+#% key_desc: name
+#% description: Name of input raster map
+#% required: yes
+#%end
+#%flag
+#%  key: m
+#%  description: Move map instead of copying it
+#%end
+#%flag
+#%  key: r
+#%  description: Reverse action: Convert from GRASS 7 to GRASS 4-6 format
+#%end
+
+if  [ -z "$GISBASE" ] ; then
+    echo "You must be in GRASS GIS to run this program." 1>&2
+    exit 1
+fi
+
+if [ "$1" != "@ARGS_PARSED@" ] ; then
+    exec g.parser "$0" "$@"
+fi
+
+
+eval `g.gisenv`
+: ${GISBASE?} ${GISDBASE?} ${LOCATION_NAME?} ${MAPSET?}
+LOCATION="$GISDBASE"/"$LOCATION_NAME"/"$MAPSET"
+
+cd "$LOCATION"
+
+
+# to copy or move?
+if [ $GIS_FLAG_M -eq 0 ] ; then
+   MVCMD="cp"
+else
+   MVCMD="mv"
+fi
+
+
+if [ $GIS_FLAG_R -eq 0 ] ; then
+
+    # make new $MAPSET/raster/ dir if needed
+    if [ ! -e raster ] ; then
+	mkdir raster
+    fi
+    if [ ! -d raster ] ; then
+	echo "ERROR: Could not convert map." 1>&2
+	exit 1
+    fi
+
+    g.findfile element=cell mapset=. file="$GIS_OPT_MAP" > /dev/null
+    if [ $? -ne 0 ] ; then
+	echo "Raster map <$GIS_OPT_MAP> not found in current mapset." 1>&2
+	exit 1
+    fi
+
+    # make new $MAPSET/raster/$MAPNAME dir
+    if [ ! -e "raster/$GIS_OPT_MAP" ] ; then
+	mkdir "raster/$GIS_OPT_MAP"
+    fi
+    if [ ! -d "raster/$GIS_OPT_MAP" ] ; then
+	echo "ERROR: Could not convert map." 1>&2
+	exit 1
+    fi
+
+    for ELEMENT in cats cell cellhd colr fcell grid3 hist ; do
+	if [ -e "$ELEMENT/$GIS_OPT_MAP" ] ; then
+	    $MVCMD "$ELEMENT/$GIS_OPT_MAP" "raster/$GIS_OPT_MAP/$ELEMENT"
+	    if  [ $? -ne 0 ] ; then
+		echo "ERROR converting map. (element: $ELEMENT)" 1>&2
+		exit 1
+	    fi
+	fi
+    done
+
+    if [ -d "cell_misc/$GIS_OPT_MAP/" ] ; then
+	$MVCMD "cell_misc/$GIS_OPT_MAP"/* "raster/$GIS_OPT_MAP/"
+	if  [ $? -ne 0 ] ; then
+	    echo "ERROR converting map. (element: cell_misc/)" 1>&2
+	    exit 1
+	fi
+
+	if [ $GIS_FLAG_M -eq 1 ] ; then
+	    rmdir "cell_misc/$GIS_OPT_MAP/"
+	    if  [ $? -ne 0 ] ; then
+		echo "WARNING: problem removing old map. (element: cell_misc/)" 1>&2
+	    fi
+	fi
+    fi
+
+else
+    # reverse: make a GRASS 6 map from a GRASS 7 map
+    if [ ! -d "raster/$GIS_OPT_MAP/" ] ; then
+	echo "Raster map <$GIS_OPT_MAP> not found in current mapset." 1>&2
+	exit 1
+    fi
+
+
+    for ELEMENT in cats cell cellhd colr fcell grid3 hist ; do
+	# make new $MAPSET/raster/ dir if needed
+	if [ ! -e $ELEMENT ] ; then
+	    mkdir $ELEMENT
+	fi
+	if [ ! -d $ELEMENT ] ; then
+	    echo "ERROR: Could not convert map." 1>&2
+	    exit 1
+	fi
+
+
+	if [ -e "raster/$GIS_OPT_MAP/$ELEMENT" ] ; then
+	    $MVCMD "raster/$GIS_OPT_MAP/$ELEMENT" "$ELEMENT/$GIS_OPT_MAP"
+	    if  [ $? -ne 0 ] ; then
+		echo "ERROR converting map. (element: $ELEMENT)" 1>&2
+		exit 1
+	    fi
+	fi
+    done
+
+    for ELEMENT in f_format f_quant f_range null range reclassed_to ; do
+	if [ -e "raster/$GIS_OPT_MAP/$ELEMENT" ] ; then
+	    if [ ! -e cell_misc ] ; then
+		mkdir cell_misc
+	    fi
+	    if [ ! -d cell_misc ] ; then
+		echo "ERROR: Could not convert map." 1>&2
+		exit 1
+	    fi
+
+	    if [ ! -e "cell_misc/$GIS_OPT_MAP" ] ; then
+		mkdir "cell_misc/$GIS_OPT_MAP"
+	    fi
+	    if [ ! -d "cell_misc/$GIS_OPT_MAP" ] ; then
+		echo "ERROR: Could not convert map." 1>&2
+		exit 1
+	    fi
+
+
+	    $MVCMD "raster/$GIS_OPT_MAP/$ELEMENT" "cell_misc/$GIS_OPT_MAP"
+	    if  [ $? -ne 0 ] ; then
+		echo "ERROR converting map. (element: $ELEMENT)" 1>&2
+		exit 1
+	    fi
+	fi
+    done
+
+    if [ $GIS_FLAG_M -eq 1 ] ; then
+	rmdir "raster/$GIS_OPT_MAP/"
+	if  [ $? -ne 0 ] ; then
+	    echo "WARNING: problem removing old map. Left over files:" 1>&2
+	    ls "raster/$GIS_OPT_MAP/"
+	fi
+    fi
+
+fi
+


Property changes on: grass-addons/grass7/grass7/raster/r.convert/r.convert
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.convert/r.convert.all
===================================================================
--- grass-addons/grass7/grass7/raster/r.convert/r.convert.all	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.convert/r.convert.all	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,55 @@
+#!/bin/sh
+############################################################################
+#
+# MODULE:       r.convert.all
+# AUTHOR:       M. Hamish Bowman, Dunedin, New Zealand
+# PURPOSE:      Converts all GRASS 4-6 raster maps in current mapset to
+#		 GRASS 7 raster map format
+# COPYRIGHT:    (c) 2007 Hamish Bowman, and the GRASS Development Team
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+#%Module
+#% description: Converts all GRASS 4-6 raster maps in current mapset to GRASS 7 raster map format
+#% keywords: raster, import, conversion, bulk
+#%end
+#%flag
+#%  key: m
+#%  description: Move maps instead of copying then
+#%end
+#%flag
+#%  key: r
+#%  description: Reverse action: Convert from GRASS 7 to GRASS 4-6 format
+#%end
+
+if  [ -z "$GISBASE" ] ; then
+    echo "You must be in GRASS GIS to run this program." 1>&2
+    exit 1
+fi
+
+if [ "$1" != "@ARGS_PARSED@" ] ; then
+    exec g.parser "$0" "$@"
+fi
+
+if [ $GIS_FLAG_M -eq 1 ] ; then
+    MV_FLAG="-m"
+else
+    MV_FLAG=""
+fi
+
+if [ $GIS_FLAG_R -eq 1 ] ; then
+    REV_FLAG="-r"
+else
+    REV_FLAG=""
+fi
+
+
+for MAP in `g.mlist type=rast mapset=.` ; do
+    r.convert map="$MAP" $MV_FLAG $REV_FLAG
+    if [ $? -ne 0 ] ; then
+	echo "Error converting <$MAP>" 1>&2
+    fi
+done


Property changes on: grass-addons/grass7/grass7/raster/r.convert/r.convert.all
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.fuzzy/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+SUBDIRS = \
+	r.fuzzy.set \
+	r.fuzzy.logic \
+	r.fuzzy.system \
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: parsubdirs

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../../..
+
+PGM = r.fuzzy.logic
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,29 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+#define _AND	1
+#define _OR		2
+#define _NOT	3
+#define _IMP	4
+
+#define ZADEH 			1
+#define PRODUCT			2	
+#define DRASTIC			3
+#define LUKASIEWICZ	4
+#define FODOR				5
+#define HAMACHER		6
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+float f_and(float cellx, float celly, int family);
+float f_or(float cellx, float celly, int family);
+float f_imp(float cellx, float celly, int family);
+float f_not(float cellx, int family);
+

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/logic.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/logic.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/logic.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,105 @@
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+float f_and(float x, float y, int family) {
+
+	switch (family) {
+		
+			case ZADEH:
+		return MIN(x,y);
+			break;
+		
+			case PRODUCT:
+		return x*y;
+			break;	
+		
+			case DRASTIC:
+		return MAX(x, y) == 1 ? MIN(x, y) : 0;
+			break;	
+		
+			case LUKASIEWICZ:
+		return MAX((x+y-1),0);
+			break;
+		
+			case FODOR:
+		return (x+y)>1 ? MIN(x,y) : 0;	
+			break;
+			
+			case HAMACHER:
+		return (x==y==0) ? 0 : (x*y)/((x+y)-x*y);	
+			break;
+			
+
+				
+	}
+	return -1; /* error */
+}
+
+float f_or(float x, float y, int family) {
+			float b;
+	switch (family) {
+		
+			case ZADEH:
+		return MAX(x,y);
+			break;
+		
+			case PRODUCT:
+		return x + y -x * y;
+			break;	
+		
+			case DRASTIC:
+		return (MIN(x, y) == 0) ? MAX(x, y) : 1;
+			break;	
+		
+			case LUKASIEWICZ:
+		return MIN((x+y),1);
+			break;
+	
+			case FODOR:
+		return (x+y<1) ? MAX(x,y) : 1;		
+			break;
+			
+			case HAMACHER:
+		return (x+y)/(1+x*y);
+			break;
+	}
+	return -1; /* error */
+}
+
+float f_imp(float x, float y, int family) {
+		
+	switch (family) {
+			
+			case ZADEH:
+		return (x <= y) ? 1 : y;
+			break;
+
+			case PRODUCT:
+		return MIN(y/x,1);
+			break;	
+		
+			case DRASTIC:
+		return -1; /* not avaialble */	
+			break;	
+			
+			case LUKASIEWICZ:
+		return MIN((1-x+y),1);	
+			break;
+			
+			case FODOR:
+		return (x<=y) ? 1 : MAX(1-x,y);		
+			break;
+	}
+	return -1; /* error */	
+}
+
+float f_not(float x, int family) {
+	
+		if (family==HAMACHER)
+	return (1-x)/(1+x);
+		else
+	return ((1-x)<0 || (1-x)>1) ? -1 : 1-x;
+}
+
+

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,240 @@
+/* ***************************************************************************
+ *
+ * MODULE:       r.fuzzy.logic
+ * AUTHOR(S):    Jarek Jasiewicz <jarekj amu.edu.pl>
+ * PURPOSE:      Performs logical operations on membership images created with 
+ *                   r.fuzzy or different method. Use families for fuzzy logic
+ * COPYRIGHT:    (C) 1999-2010 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ****************************************************************************
+ */
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int main(int argc, char *argv[])
+{
+
+	struct GModule *module;
+	struct Option *par_inputx,
+								*par_inputy,
+								*par_output,
+								*par_operation,
+								*par_family;
+	
+	struct Cell_head cellhdx;
+	struct Cell_head cellhdy;  
+  struct FPRange membership_range;
+  struct History history;
+
+	char *mapsetx, *mapsety;
+	char *inputx, *inputy;
+	char *output;
+	int nrows, ncols;
+	int row, col;
+	int infdx, infdy, outfd;
+	void *in_bufx, *in_bufy;
+	unsigned char *out_buf;
+	float tmp;
+	DCELL c_min, c_max;
+	int family, operator;
+	
+	G_gisinit(argv[0]);
+	
+    module = G_define_module();
+    module->keywords = _("raster, fuzzy logic");
+    module->description =
+        _("xxxx");
+
+	par_inputx = G_define_standard_option(G_OPT_R_INPUT);
+    par_inputx->description = _("x operand (membership map)");
+    par_inputx->key = "xmap";
+  
+    par_inputy = G_define_standard_option(G_OPT_R_INPUT);
+    par_inputy->description = _("y operand (membership map)");
+    par_inputy->key = "ymap";
+    par_inputy->required = NO;
+  
+    par_output = G_define_standard_option(G_OPT_R_OUTPUT);
+	par_output->description = _("Resulting map");
+
+	par_operation=G_define_option();
+	par_operation->key = "operator";
+	par_operation->type = TYPE_STRING;
+	par_operation->options = "AND,OR,NOT,IMP";
+	par_operation->answer = "AND";
+	par_operation->multiple = NO;
+	par_operation->required = YES;
+	par_operation->description = _("Fuzzy logic operation");
+	
+	par_family=G_define_option();
+	par_family->key = "family";
+	par_family->type = TYPE_STRING;
+	par_family->options = "Zadeh,product,drastic,Lukasiewicz,Fodor,Hamacher";
+	par_family->answer = "Zadeh";
+	par_family->multiple = NO;
+	par_family->required = YES;
+	par_family->description = _("Fuzzy logic family");
+	
+  	if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+	
+	inputx=par_inputx->answer;
+	inputy=par_inputy->answer;
+	output=par_output->answer;
+	
+			if (!strcmp(par_operation->answer, "AND"))
+	operator=_AND;
+		else if (!strcmp(par_operation->answer, "OR"))
+	operator=_OR;
+		else if (!strcmp(par_operation->answer, "NOT"))
+	operator=_NOT;
+		else if (!strcmp(par_operation->answer, "IMP"))
+	operator=_IMP;
+	  
+  		if (!strcmp(par_family->answer, "Zadeh"))
+	family=ZADEH;
+		else if (!strcmp(par_family->answer, "product"))
+	family=PRODUCT;
+		else if (!strcmp(par_family->answer, "drastic"))
+	family=DRASTIC;
+		else if (!strcmp(par_family->answer, "Lukasiewicz"))
+	family=LUKASIEWICZ;
+		else if (!strcmp(par_family->answer, "Fodor"))
+	family=FODOR;
+			else if (!strcmp(par_family->answer, "Hamacher"))
+	family=HAMACHER;
+	
+		if(operator == _NOT && inputy)
+	G_warning("Negation is unary operaton ymap is ignored");
+	
+		if(operator != _NOT && !inputy)
+	G_fatal_error("For binary operation (AND, OR, IMP) ymap is required");
+	
+		if(family == DRASTIC && operator == _IMP)
+  G_fatal_error("implication is not available for <drastic> family");
+	
+	/* end of interface */
+	
+	mapsetx = (char *)G_find_raster2(inputx, "");
+	
+	  if (mapsetx == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), inputx);
+	
+	infdx = Rast_open_old(inputx, mapsetx);
+	Rast_get_cellhd(inputx, mapsetx, &cellhdx);
+	
+		if (Rast_map_type(inputx, mapsetx) != FCELL_TYPE)
+	 G_fatal_error(_("<%s> is not of type CELL"), inputx);
+	 
+	Rast_init_fp_range(&membership_range);
+	Rast_read_fp_range(inputx,mapsetx,&membership_range);
+	Rast_get_fp_range_min_max(&membership_range, &c_min, &c_max);
+		if(c_min<0 || c_max>1)
+	G_fatal_error("Membership out of range");
+	
+	in_bufx = Rast_allocate_buf(FCELL_TYPE);
+	
+		if(inputy) {
+	
+	mapsety = (char *)G_find_raster2(inputy, "");
+	
+	  if (mapsety == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), inputy);
+	
+	infdy = Rast_open_old(inputy, mapsety);
+	Rast_get_cellhd(inputy, mapsety, &cellhdy);
+
+		if (Rast_map_type(inputy, mapsety) != FCELL_TYPE);
+	G_fatal_error(_("<%s> is not of type CELL"), inputy);
+	
+	Rast_init_fp_range(&membership_range);
+	Rast_read_fp_range(inputy,mapsety,&membership_range);
+	Rast_get_fp_range_min_max(&membership_range, &c_min, &c_max);
+		if(c_min<0 || c_max>1)
+	G_fatal_error("Membership out of range");
+	
+	
+	in_bufy = Rast_allocate_buf(FCELL_TYPE);
+		
+		} /* end if inputy */
+	
+	nrows = Rast_window_rows();
+	ncols = Rast_window_cols();
+
+	outfd = Rast_open_new(output, FCELL_TYPE);
+	out_buf = Rast_allocate_buf(FCELL_TYPE);
+	
+	
+	/* binary processing */
+	for (row = 0; row < nrows; row++) {
+		G_percent(row, nrows, 2);
+		
+		FCELL fx, fy=0;
+		
+		Rast_get_row(infdx, in_bufx, row, FCELL_TYPE);
+		
+			if(inputy)
+		Rast_get_row(infdy, in_bufy, row, FCELL_TYPE);
+		
+		for (col = 0; col < ncols; col++) {
+				
+				fx = ((FCELL *) in_bufx)[col];
+					if(inputy)
+				fy = ((FCELL *) in_bufy)[col];
+
+				 if (Rast_is_f_null_value(&fx) || Rast_is_f_null_value(&fy))
+			Rast_set_f_null_value(&tmp, 1); 
+				 
+				 else
+			
+			switch (operator) {
+				case _AND:
+					//if((row+col)%100==0)
+						if(0>(tmp = f_and(fx,fy,family)))
+					G_warning("Cannot determine result at row %d, col %d", row,col);
+					break;
+				
+				case _OR:
+						if(0>(tmp=f_or(fx,fy,family)))
+					G_warning("Cannot determine result at row %d, col %d", row,col);
+					break;
+					
+				case _IMP:
+						if((tmp=f_imp(fx,fy,family))<0)
+					G_warning("Cannot determine result at row %d, col %d", row,col);
+					break;	
+				
+				case _NOT:
+						if((tmp=f_not(fx, family))<0)
+					G_warning("Cannot determine result at row %d, col %d", row,col);
+					break;
+			} /* end switch */
+			
+			((FCELL *) out_buf)[col] = tmp;
+		}
+		Rast_put_row(outfd, out_buf, FCELL_TYPE);
+	} /* end for row */
+	
+  G_free(in_bufx);
+	Rast_close(infdx);
+	
+		if(inputy) {
+  G_free(in_bufy);
+  Rast_close(infdy);
+	}
+	
+	G_free(out_buf);
+	Rast_close(outfd);
+
+	Rast_short_history(output, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(output, &history);
+	
+	exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/r.fuzzy.logic.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/r.fuzzy.logic.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.logic/r.fuzzy.logic.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,86 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>xmap</b></dt>
+<dd>Name of input x membership operand. This map must be of type FCELL with
+range 0 :1 and may require null values. Otherwise program will print error
+message and stops.
+</dd>
+<dt><b>xmap</b></dt>
+<dd>Name of input y membership operand. This map must be of type FCELL with
+range 0 :1 and may require null values. Otherwise program will print error
+message and stops. This map is optional bit is required for all operation except
+NOT
+</dd>
+<dt><b>operator</b></dt>
+<dd>A fuzzy set operators are generalization of crisp operators. There is more
+than one possible generalization of every opeartor. There are three operations:
+fuzzy complements, fuzzy intersections, and fuzzy unions. Addational implication
+operator is also provided.
+<ul>
+<li>fuzzy intersection (<b>AND</b>) use T-norm of given family for calculation;
+<li>fuzzy union (<b>OR</b>) use T-conorm of given family for calculation;
+<li>fuzzy complement (<b>NOT</b>) fuzzy negation ussualy 1-x;
+<li>fuzzy implication (<b>IMP</b>) use residuum of given family if available;
+</ul>
+</dd>
+<dt><b>family</b></dt>
+<dd>T-norms, T-conorms and residuals are a generalization of the two-valued
+logical conjunction,  disjunction and implication used by boolean logic, for
+fuzzy logics. Because there is more than one possible generalisation of logial
+operations, r.fuzzy.logic provides 6 most popular families for fuzzy operations:
+<ul>
+<li><b>Zadeh</b> with minimum (Godel) t-norm and maximum T-conorm;
+<li><b>product</b> with product T-norm and probabilistic sum as T-conorm;
+<li><b>drastic</b> with drastic T-norm and drastic T-conorm;
+<li><b>Łukasiewicz</b> with Łukasiewicz T-norm and bounded sum as a T-conorm;
+<li><b>Fodor</b> with nilpotent minimum as T-norm and nilpotent maximum as
+T-conorm;
+<li><b>Hamacher</b> (simplified) with Hamacher product as T-norm and Einstein
+sum as T-conorm;
+</ul>
+There is no residuum for drastic and Hamacher families.
+For more details see <a href="http://www.jstatsoft.org/v31/i02">Meyer D, Hornik
+K (2009)</a>; <a href="http://en.wikipedia.org/wiki/T-norm">T-norms</a>; 
+</dd>
+</dl>
+<h2>OUTPUTS</h2>
+<dl>
+<dt><b>output</b></dt>
+<dd>Map containing result of two-values operations. Multivalued operations will
+be avaialbel in the future. Map is always of type FCELLS and contains values
+from 0 (no membership) to 1 (full membership). Values between 0 and 1 indicate
+partial membership</dd>
+</dl>
+<h2>SEE ALSO</h2>
+<em>
+<a href="r.fuzzy.html">r.fuzzy</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+</em>
+
+
+<h2>REFERENCES</h2>
+
+Zadeh, L.A. (1965). "Fuzzy sets". Information and Control 8 (3): 338–353.
+doi:10.1016/S0019-9958(65)90241-X. ISSN 0019-9958.<p>
+
+Novák, Vilém (1989). Fuzzy Sets and Their Applications. Bristol: Adam Hilger.
+ISBN 0-85274-583-4.<p>
+
+Klir, George J.; Yuan, Bo (1995). Fuzzy sets and fuzzy logic: theory and
+applications. Upper Saddle River, NJ: Prentice Hall PTR. ISBN 0-13-101171-5.<p>
+
+Klir, George J.; St Clair, Ute H.; Yuan, Bo (1997). Fuzzy set theory:
+foundations and applications. Englewood Cliffs, NJ: Prentice Hall. ISBN
+0133410587.<p>
+
+Meyer D, Hornik K (2009a). \Generalized and Customizable Sets in R." Journal of
+Statistical Software, 31(2), 1{27. URL http://www.jstatsoft.org/v31/i02/.<p>
+
+Meyer D, Hornik K (2009b). sets: Sets, Generalized Sets, and Customizable Sets.
+R~package version~1.0, URL http://CRAN.R-project.org/package=sets.<p>
+
+<h2>AUTHOR</h2>
+Jarek  Jasiewicz
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>
+

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../../..
+
+PGM = r.fuzzy.set
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
+

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/boundary.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/boundary.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/fuzzy.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/fuzzy.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/fuzzy.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,52 @@
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+float fuzzy (FCELL cell) {
+
+	float x, m;
+	
+	if (!side) { /* both left and right */
+	
+			if (cell <= p[0] || cell >= p[3])
+		return 0.;
+			if (cell >= p[1] && cell <= p[2])
+		return 1.;	
+
+		x = (cell<p[1]) ? (cell-p[0])/(p[1]-p[0])
+				: (p[3]-cell)/(p[3]-p[2]);
+	}
+	
+	if (side) { /* left: 1 OR right: 2 */
+
+			if (cell <= p[0])
+		return (side == 1) ? 0. : 1.;
+			if (cell >= p[1])
+		return (side == 1) ? 1. : 0.;
+	
+		x = (side == 1) ? (cell-p[0])/(p[1]-p[0])
+				: (p[1]-cell)/(p[1]-p[0]);
+	}
+
+		if (type == LINEAR)
+	return x;
+		
+		if (type == JSHAPE) {
+	m = (shape < 0) ? pow(2,1+shape) 
+			: pow(2,exp(2*shape));	
+	return pow(tan(x * PI4),m);
+		}
+		
+		if (type == GSHAPE) {
+	m = (shape > 0) ? pow(2,1-shape) 
+			: pow(2,exp(-2*shape));	
+	return pow(tan(x * PI4),1/m);	
+		}
+	
+			if(type==SSHAPE) {
+		m =  pow(2,exp(2*abs(shape)));
+		return (shape < 0) ? pow(1-cos(x*PI2),m)
+			: pow(sin(x*PI2),m);
+	}
+
+return -1; /* error */
+}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,36 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <grass/raster.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+/*
+PI2= PI/2
+PI4= PI/4
+*/
+#ifndef PI2
+	#define PI2 (2*atan(1))
+#endif
+
+#ifndef PI4
+	#define PI4 (atan(1))
+#endif
+	
+
+#define LINEAR 0
+#define SSHAPE 1
+#define JSHAPE 2
+#define GSHAPE 3
+
+#define BOTH 0
+#define LEFT 1
+#define RIGHT 2
+
+extern char *input, *output;
+extern float shape, height;
+extern int type, side;
+extern double p[4]; /* inflection points */
+extern int num_points;
+
+float fuzzy (FCELL cell);

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,239 @@
+/* ***************************************************************************
+ *
+ * MODULE:       r.fuzzy.set
+ * AUTHOR(S):    Jarek Jasiewicz <jarekj amu.edu.pl>
+ * PURPOSE:      Calculate membership value of any raster map according user's rules
+ * COPYRIGHT:    (C) 1999-2010 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ****************************************************************************
+ */
+
+#define MAIN
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+char *input, *output;
+float shape, height;
+int type, side;
+double p[4]; /* inflection points */
+int num_points;
+
+int main(int argc, char *argv[])
+{
+	struct GModule *module;
+	struct Option *par_input,
+								*par_output,
+								*par_points,
+								*par_side,
+								*par_type,
+								*par_height,
+								*par_shape;
+	
+	struct Cell_head cellhd; 
+  struct History history;
+	
+	
+	char *mapset;
+	int nrows, ncols;
+  int row, col;
+  int infd, outfd;
+  void *in_buf;
+	unsigned char *out_buf;
+  RASTER_MAP_TYPE raster_type;
+  FCELL tmp=0;
+	
+	G_gisinit(argv[0]);	
+	
+	par_input = G_define_standard_option(G_OPT_R_INPUT);
+  par_input->description = _("Raster map to be fuzzified");
+  
+  par_output = G_define_standard_option(G_OPT_R_OUTPUT);
+	par_output->description = _("Membership map");
+	
+	par_points=G_define_option();
+	par_points->key = "points";
+	par_points->type = TYPE_STRING;
+	par_points->answer = "a,b[,c,d]";
+	par_points->multiple = YES;
+	par_points->required = YES;
+	par_points->description = _("Inflection points: a,b[,c,d]");
+	
+	par_side=G_define_option();
+	par_side->key = "side";
+	par_side->type = TYPE_STRING;
+	par_side->options = "both,left,right";
+	par_side->answer = "both";
+	par_side->multiple = NO;
+	par_side->required = YES;
+	par_side->description = _("Fuzzy range");
+	
+	par_type=G_define_option();
+	par_type->key = "boundary";
+	par_type->type = TYPE_STRING;
+	par_type->options = "Linear,S-shaped,J-shaped,G-shaped";
+	par_type->answer = "S-shaped";
+	par_type->multiple = NO;
+	par_type->required = YES;
+	par_type->description = _("Type of fuzzy boundaries");
+	par_type->guisection = _("Default options");
+	
+	par_shape=G_define_option();
+	par_shape->key = "shape";
+	par_shape->type = TYPE_DOUBLE;
+	par_shape->options = "-1,1";
+	par_shape->answer = "0.";
+	par_shape->multiple = NO;
+	par_shape->required = YES;
+	par_shape->description = _("Shape modifier: -1 to 1");
+	par_shape->guisection = _("Default options");
+	
+	par_height=G_define_option();
+	par_height->key = "height";
+	par_height->type = TYPE_DOUBLE;
+	par_height->options = "0,1";
+	par_height->answer = "1.";
+	par_height->multiple = NO;
+	par_height->required = YES;
+	par_height->description = _("Membership height: 0 to 1");
+	par_height->guisection = _("Default options");
+	
+	    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+	
+	input=par_input->answer;
+	output=par_output->answer;
+		
+		if (!strcmp(par_type->answer, "Linear"))
+	type=LINEAR;
+		else if (!strcmp(par_type->answer, "S-shaped"))
+	type=SSHAPE;
+		else if (!strcmp(par_type->answer, "J-shaped"))
+	type=JSHAPE;
+		else if (!strcmp(par_type->answer, "G-shaped"))
+	type=GSHAPE;
+	
+			if (!strcmp(par_side->answer, "both"))
+	side=BOTH;
+		else if (!strcmp(par_side->answer, "left"))
+	side=LEFT;
+		else if (!strcmp(par_side->answer, "right"))
+	side=RIGHT;
+	
+	shape = atof(par_shape->answer);
+		if(shape<-1. || shape>1.)
+	G_fatal_error(_("Shape modifier must be between -1 and 1 but is %f"),shape);
+	
+	height = atof(par_height->answer);
+		if(height>1 || height<0)
+	G_fatal_error(_("Heght modifier must be between 0 and 1 but is %f"),height);
+		
+	num_points=sscanf(par_points->answer,
+			"%lf,%lf,%lf,%lf", 
+			&p[0], &p[1], &p[2], &p[3]);
+	
+		if(!side && num_points != 4)
+	G_fatal_error(_("Wrong number of values: got %d but need 4"),
+		      num_points);
+	
+			if(side && num_points != 2)
+	G_fatal_error(_("Wrong number of values: got %d but need 2"),
+		      num_points);
+	
+	if (num_points==2) {
+			if(	p[0]>p[1])
+		G_fatal_error(_("Point sequence must be: a <= b"));
+	} else {
+			if(	p[0]>p[1]||p[1]>p[2]||p[2]>p[3])
+		G_fatal_error(_("Point sequence must be: a <= b; b <= c; c <= d;"));	
+	}
+
+	/* end of interface */
+
+	mapset = (char *)G_find_raster2(input, "");
+	
+	    if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), input);
+	
+	infd = Rast_open_old(input, mapset);
+	Rast_get_cellhd(input, mapset, &cellhd);
+	
+	nrows = Rast_window_rows();
+	ncols = Rast_window_cols();
+	raster_type = Rast_map_type(input,mapset);
+	
+	outfd = Rast_open_new(output, FCELL_TYPE);
+	
+	in_buf = Rast_allocate_buf(raster_type);
+	out_buf = Rast_allocate_buf(FCELL_TYPE);
+	
+	/* processing */
+	for (row = 0; row < nrows; row++) {
+		G_percent(row, nrows, 2);
+		CELL c;
+		FCELL f;
+		DCELL d;
+		
+	Rast_get_row(infd, in_buf, row, raster_type);
+
+		for (col = 0; col < ncols; col++) {
+				 
+			switch (raster_type) {
+
+				case CELL_TYPE:
+			c = ((CELL *) in_buf)[col];
+				if(Rast_is_null_value(&c,CELL_TYPE))
+			Rast_set_f_null_value(&tmp, 1);
+				else {
+					if(0>(tmp = fuzzy((FCELL) c)))
+			G_warning("Cannot determine memebership at row %d, col %d", row,col);
+			((FCELL *) out_buf)[col] = tmp;
+				}
+			break;
+
+				case FCELL_TYPE:
+			f = ((FCELL *) in_buf)[col];
+				if(Rast_is_null_value(&f,FCELL_TYPE))
+			Rast_set_f_null_value(&tmp, 1);
+				else {			
+				tmp = fuzzy((FCELL) f);
+				if(0>(tmp = fuzzy((FCELL) f)))
+			G_warning("Cannot determine memebership at row %d, col %d", row,col);
+			((FCELL *) out_buf)[col] = tmp;
+				}
+			break;
+
+				case DCELL_TYPE:
+			d = ((DCELL *) in_buf)[col];
+				if(Rast_is_null_value(&d,DCELL_TYPE))
+			Rast_set_f_null_value(&tmp, 1);
+				else {
+				if(0>(tmp = fuzzy ((FCELL) d)))
+			G_warning("Cannot determine memebership at row %d, col %d", row,col);
+			((FCELL *) out_buf)[col] = tmp;
+				}
+			break;
+	    }
+		}
+		Rast_put_row(outfd, out_buf, FCELL_TYPE);
+	} /* end for */
+	
+  G_free(in_buf);
+  G_free(out_buf);
+
+	Rast_close(infd);
+	Rast_close(outfd);
+
+	Rast_short_history(output, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(output, &history);
+	
+	exit(EXIT_SUCCESS);
+}
+
+	
+	

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/r.fuzzy.set.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/r.fuzzy.set.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/r.fuzzy.set.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,148 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>input</b></dt>
+<dd>Name of input raster map to be fuzified. This map may be of any type and may
+require null values. 
+</dd>
+<dt><b>points</b></dt>
+<dd>A list containing 4 (A,B,C,D) or 2 A,B) points defining set boundaries.
+Points must not to be in map range, but it may lead to only 0 o 1 membership for
+the whole map. For "both" side parameters range between A and D defines base,
+but range between B and C core of the fuzzy set. Between A and B and C and D are
+set's boundaries. If side is "both" it require 4 points, else 2 points.
+<center>
+<h3>Fuzzy set definition:</h3>
+<img src="set.png" border=1>
+</center>
+</dd>
+<dt><b>side</b></dt>
+<dd>Option indicate if set is fuzzified of both sides (both), left or right
+side. See description for details.
+<center>
+<h3>Boundary definition:</h3>
+<img src=boundary.png border=1><br>
+</center>
+</dd>
+</dl>
+
+<h2>OUTPUTS</h2>
+<dl>
+<dt><b>output</b></dt>
+<dd>Map containing membership value of original map. Map is alvays of type
+FCELLS and contains values from 0 (no membership) to 1 (full membership). Values
+between 0 and 1 indicate partial membership</dd>
+</dl>
+<h2>FUZZY SET PARAMETERS</h2>
+<dl>
+<dt><b>boundary</b></dt>
+<dd>Parameter definied the shape of the fuzzy boundary. The default and most
+popular is S-shaped, linear, J-shaped and G-shaped boundaries are also
+available. The same boundaires are appled to the both sides.</dd>
+
+<dt><b>shape</b></dt>
+<dd>Optional shape modifier. Range from -1 to 1. The default value is 0 and
+shoud  not be changed in most of the time. The negative values indicate more
+dilatant set, the positive values more concentrate set. See description for
+details.
+<center>
+<h3>Impact of shape parameter on shape boundary:</h3>
+<img src=shape.png border=1>
+</center>
+</dd>
+<dt><b>height</b></dt>
+<dd>Optional height modifier. Range from 0 to 1. The default value is 1 and
+indicate full membership beteen points B and C. If height is lesser than one the
+maximum memebrship is equal to height. See image: Fuzzy set definition.</dd>
+</dl>
+
+<h2>DESCRIPTION</h2>
+
+<h4>Definition of fuzzy set</h4>
+Fuzzy sets are sets whose elements have degrees of membership. Zadeh (1965)
+introduced Fuzzy sets as an extension of the classical notion of set. Classical 
+membership of elements in a set are binary terms: an element either belongs or
+does not belong to the set. Fuzzy set theory use the gradual assessment of the
+membership of elements in a set. A membership function valued in the real unit
+interval [0, 1]. Classical sets, are special cases of the membership functions
+of fuzzy sets, if the latter only take values 0 or 1. Classical sets are in
+fuzzy set theory usually called crisp sets. The fuzzy set theory can be used in
+a wide range of domains in which information is  imprecise, such as most of the
+GIS operations.
+
+
+<h2>NOTES</h2>
+<h4>Calculation of boundary shape</h4>
+Depending on type of the boundary different equation are used to determine its
+shape:
+<p>
+<b>Linear:</b> the membership is calculated according following equation:<br>
+<pre><code>
+value  <=  A -> x = 0
+A< value > B -> x = (value-A)/(B-A)
+B <= value >= C -> x = 1
+C< value > D -> x = (D-value)/(D-C)
+value  >=  D -> x = 0
+
+where x: membership
+</code></pre>
+<p>
+<b>S-shaped:</b> it use following equation:
+<pre><code>
+sin(x * Pi/2)^m (for positive shape parameter)
+1-cos(x * Pi/2)^m (for nagative shape parameter)
+
+where x: membership, and 
+m = 2^exp(2,shape) (for positive shape parameter)
+m = 2^(1+shape) (for negative shape parameter)
+where m: shape parameter.
+</code></pre>
+
+For default shape parameter = 0 m is = 2 whcich is most common parameter for
+that equation.
+
+<p>
+<b>G-shaped and J shaped:</b> it use following equations: 
+<pre><code>
+tan(x * Pi/4)^m (for J-shaped)
+tan(x * Pi/4)^1/m (for G-shaped)
+
+where x: membership, and 
+m = 2^exp(2,shape) (for positive shape parameter)
+m = 2^(1+shape) (for negative shape parameter)
+where m: shape parameter.
+</code></pre>
+ 
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.fuzzy.logic.html">r.fuzzy.logic</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+</em>
+
+
+<h2>REFERENCES</h2>
+
+<p>Zadeh, L.A. (1965). "Fuzzy sets". Information and Control 8 (3): 338–353.
+doi:10.1016/S0019-9958(65)90241-X. ISSN 0019-9958.</P>
+
+<p>Novák, Vilém (1989). Fuzzy Sets and Their Applications. Bristol: Adam Hilger.
+ISBN 0-85274-583-4.</P>
+
+<p>Klir, George J.; Yuan, Bo (1995). Fuzzy sets and fuzzy logic: theory and
+applications. Upper Saddle River, NJ: Prentice Hall PTR. ISBN 0-13-101171-5.</P>
+
+<p>Klir, George J.; St Clair, Ute H.; Yuan, Bo (1997). Fuzzy set theory:
+foundations and applications. Englewood Cliffs, NJ: Prentice Hall. ISBN
+0133410587.</P>
+
+<p>Meyer D, Hornik K (2009a). \Generalized and Customizable Sets in R." Journal
+of Statistical Software, 31(2), 1{27. URL http://www.jstatsoft.org/v31/i02/.</P>
+
+Meyer D, Hornik K (2009b). sets: Sets, Generalized Sets, and Customizable Sets.
+R~package version~1.0, URL http://CRAN.R-project.org/package=sets.<p>
+
+<h2>AUTHOR</h2>
+Jarek  Jasiewicz
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/set.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/set.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/shape.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.set/shape.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../../..
+
+PGM = r.fuzzy.system
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/f_result.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/f_result.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.map
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.map	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.map	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,25 @@
+#flood.map
+
+	%elevation
+$ low {right; 2,4; sshaped; 0; 1}
+$ moderate {both; 2,4,5,10; sshaped; 0; 1}
+$ high {left; 5,10; sshaped; 0; 1}
+
+	%distance
+$ near {right; 30,70; sshaped; 0; 1}
+$ medium {both; 30,70,100,150; sshaped; 0; 1}
+$ far {both; 100,150,200,300; sshaped; 0; 1}
+$ veryfar {left; 200,300; sshaped; 0; 1}
+	
+	%accum_abs
+$ low {right; 500,5000; sshaped; 0; 1}
+$ $ high {left; 500,5000; sshaped; 0; 1}
+
+#output map
+
+	%_OUTPUT_
+$ none {both; 0,20,20,40; linear; 0;1}
+$ small {both; 20,40,40,60; linear; 0;1}
+$ moderate {both; 40,60,60,80; linear; 0;1}
+$ high {both; 60,80,80,100; linear; 0;1}
+$ veryhigh {both; 80,100,100,120; linear; 0;1}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.rul
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.rul	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/flood.rul	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,6 @@
+#flood.rul
+$ none {distance = veryfar | elevation = high}
+$ small {distance ~ near & accum_abs = high}
+$ moderate {(distance = medium | distance = far) & (elevation = low | elevation = moderate)}
+$ high {(distance = medium & elevation = low)|(distance = near & elevation = moderate)}
+$ veryhigh {distance = near & elevation = low}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/fuzzylogic.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/fuzzylogic.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/fuzzylogic.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,134 @@
+#include "local_proto.h"
+
+float fuzzy(FCELL cell, SETS * set)
+{
+
+    float x;
+
+    if (!set->side) {		/* both left and right */
+
+	if (cell <= set->points[0] || cell >= set->points[3])
+	    return 0.;
+	if (cell >= set->points[1] && cell <= set->points[2])
+	    return 1.;
+
+	x = (cell <
+	     set->points[1]) ? (cell - set->points[0]) / (set->points[1] -
+							  set->points[0])
+	    : (set->points[3] - cell) / (set->points[3] - set->points[2]);
+    }
+
+    if (set->side) {		/* left: 1 OR right: 2 */
+
+	if (cell <= set->points[0])
+	    return (set->side == 1) ? 0. : 1.;
+	if (cell >= set->points[1])
+	    return (set->side == 1) ? 1. : 0.;
+
+	x = (set->side ==
+	     s_LEFT) ? (cell - set->points[0]) / (set->points[1] -
+						  set->points[0])
+	    : (set->points[1] - cell) / (set->points[1] - set->points[0]);
+    }
+
+    switch (set->shape) {
+    case s_LINEAR:
+	break;
+    case s_SSHAPE:
+	x = pow(sin(x * PI2), 2);
+	break;
+    case s_JSHAPE:
+	x = pow(tan(x * PI4), 2);
+	break;
+    case s_GSHAPE:
+	x = pow(tan(x * PI4), 1 / 2.);
+	break;
+    }
+
+    if (set->hedge)
+	x = (set->hedge > 0) ? pow(x, pow(2, set->hedge)) : pow(x,
+								pow(0.5,
+								    (-set->
+								     hedge)));
+
+    if (set->height < 1)
+	x = x * set->height;
+
+    return (x >= 0 && x <= 1) ? x : -1;
+}
+
+float f_and(float x, float y, logics family)
+{
+    switch (family) {
+
+    case l_ZADEH:
+	return MIN(x, y);
+	break;
+
+    case l_PRODUCT:
+	return x * y;
+	break;
+
+    case l_DRASTIC:
+	return MAX(x, y) == 1 ? MIN(x, y) : 0;
+	break;
+
+    case l_LUKASIEWICZ:
+	return MAX((x + y - 1), 0);
+	break;
+
+    case l_FODOR:
+	return (x + y) > 1 ? MIN(x, y) : 0;
+	break;
+
+    case l_HAMACHER:
+	return (x == 0||y == 0) ? 0 : (x * y) / ((x + y) - x * y);
+	break;
+
+
+
+    }
+    return -1;			/* error */
+}
+
+float f_or(float x, float y, logics family)
+{
+
+    switch (family) {
+
+    case l_ZADEH:
+	return MAX(x, y);
+	break;
+
+    case l_PRODUCT:
+	return x + y - x * y;
+	break;
+
+    case l_DRASTIC:
+	return (MIN(x, y) == 0) ? MAX(x, y) : 1;
+	break;
+
+    case l_LUKASIEWICZ:
+	return MIN((x + y), 1);
+	break;
+
+    case l_FODOR:
+	return (x + y < 1) ? MAX(x, y) : 1;
+	break;
+
+    case l_HAMACHER:
+	return (x + y) / (1 + x * y);
+	break;
+    }
+    return -1;			/* error */
+}
+
+
+float f_not(float x, logics family)
+{
+
+    if (family == l_HAMACHER)
+	return (1 - x) / (1 + x);
+    else
+	return ((1 - x) < 0 || (1 - x) > 1) ? -1 : 1 - x;
+}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/helpers.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/helpers.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/helpers.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,270 @@
+#include "local_proto.h"
+
+int get_nsets(FILE * fd, fpos_t position)
+/* get number of maps (setd) used in analysis */
+{
+
+    int nsets = 0;
+
+    fsetpos(fd, &position);
+    char buf[500];
+
+    fgetpos(fd, &position);
+
+
+    while (fgets(buf, sizeof buf, fd)) {
+	G_strip(buf);
+
+	if (*buf == '#' || *buf == 0 || *buf == '\n')
+	    continue;
+
+	if (*buf == '$')
+	    nsets++;
+
+	if (*buf == '%')
+	    break;
+    }
+    fsetpos(fd, &position);
+    return nsets;
+}
+
+
+int char_strip(char *buf, char rem)
+/* remove spaces, tabs and one addational character */
+{
+    register char *a, *b;
+
+    for (a = b = buf; *a == rem || *a == ' ' || *a == '\t'; a++);
+    if (a != b)
+	while ((*b++ = *a++));
+
+    return 0;
+}
+
+int char_copy(const char *buf, char *res, int start, int stop)
+/* copy part of the string to another string */
+{
+    register int i, j;
+
+    for (i = start, j = 0; i < stop; res[j++] = buf[i++]) ;
+    res[j] = '\0';
+
+    return 0;
+}
+
+
+int get_universe(void)
+{
+    int i, j;
+    float min = 100000000., max = 0;
+
+    resolution += 1;
+
+    for (i = 0; i < nmaps; ++i) {
+	if (s_maps[i].output)
+	    break;
+    }
+    output_index = i;
+
+    for (j = 0; j < s_maps[i].nsets; ++j) {
+
+	min = (s_maps[i].sets[j].points[0] < min) ?
+	    s_maps[i].sets[j].points[0] : min;
+
+	if (s_maps[i].sets[j].side)
+	    max = (s_maps[i].sets[j].points[1] > max) ?
+		s_maps[i].sets[j].points[1] : max;
+	else
+	    max = (s_maps[i].sets[j].points[3] > max) ?
+		s_maps[i].sets[j].points[3] : max;
+    }
+
+
+    universe = (float *)G_calloc(resolution, sizeof(float));
+    for (i = 0; i < resolution; ++i)
+	universe[i] = min + ((max - min) / resolution) * i;
+
+/* visual output */
+
+    return 0;
+}
+
+void process_coors(char *answer)
+{
+
+    struct Cell_head window;
+    double x, y;
+    int i, j;
+    int r, c;
+    int num_points;
+    float result;
+
+		visual_output = (float **)G_malloc(resolution * sizeof(float *));
+
+				for (j = 0; j < nrules; ++j) 
+		for (i = 0; i < resolution; ++i) {
+	    visual_output[i] = (float *)G_calloc(nrules + 2, sizeof(float));
+	    visual_output[i][0] = universe[i];
+		}
+			
+    Rast_get_window(&window);
+    num_points = sscanf(answer, "%lf,%lf", &x, &y);
+
+    c = (int)Rast_easting_to_col(x, &window);
+    r = (int)Rast_northing_to_row(y, &window);
+    
+		get_rows(r);
+    get_cells(c);
+    
+    result = implicate(); /* jump to different function */
+
+    for (i = 0; i < nrules; ++i)
+	fprintf(stdout, "ANTECEDENT %s: %5.3f\n", s_rules[i].outname,
+		antecedents[i]);
+
+  fprintf(stdout, "RESULT (deffuzified):  %5.3f\n", result);
+  
+  fprintf(stdout, "UNIVERSE,");
+    for (i = 0; i < nrules; ++i)
+	fprintf(stdout, "%s,", s_rules[i].outname);
+    fprintf(stdout, "AGREGATE \n");
+
+    for (i = 0; i < resolution; ++i)
+	for (j = 0; j < nrules + 2; ++j) {
+	    fprintf(stdout, "%5.3f", visual_output[i][j]);
+	    if (j < nrules + 1)
+		fprintf(stdout, ",");
+	    else
+		fprintf(stdout, "\n");
+	}
+
+			for (i = 0; i < nmaps; ++i) {
+	G_free(s_maps[i].sets);
+	if (s_maps[i].output)
+	    continue;
+		G_free(s_maps[i].in_buf);
+	Rast_close(s_maps[i].cfd);
+    }
+
+			for (j = 0; j < nrules; ++j)
+				G_free(visual_output[j]);
+    G_free(visual_output);
+    
+    G_free(antecedents);
+    G_free(s_maps);
+    G_free(s_rules);
+   
+    exit(EXIT_SUCCESS);
+}
+
+
+void show_membership(void) {
+	int i,j,k;
+	STRING cur_mapset;
+	struct FPRange map_range;
+	DCELL min, max;
+	float* map_universe;
+	
+	resolution=resolution+1;
+	map_universe = (float *)G_calloc(resolution, sizeof(float));
+
+	for(i=0;i<nmaps;++i) {
+		
+		if(s_maps[i].output)
+			continue;
+		Rast_init_fp_range(&map_range);
+		cur_mapset = (STRING)G_find_raster2(s_maps[i].name, "");
+		Rast_read_fp_range(s_maps[i].name,cur_mapset,&map_range);
+		Rast_get_fp_range_min_max(&map_range,&min, &max);
+		
+			for (k = 0; k < resolution; ++k)
+		map_universe[k] = min + ((max - min) / resolution) * k;
+		
+		fprintf(stdout,"#MAP: %s \n",s_maps[i].name);
+		
+		fprintf(stdout,"value,");
+			for(j=0;j<s_maps[i].nsets;++j) {
+		fprintf(stdout,"%s",s_maps[i].sets[j].setname);
+				if (j < s_maps[i].nsets-1)
+			fprintf(stdout, ",");
+				else
+			fprintf(stdout, "\n");
+			}
+			
+			for(k=0;k<resolution;++k) { 
+				fprintf(stdout,"%5.3f,",map_universe[k]);
+				for(j=0;j<s_maps[i].nsets;++j) {
+					fprintf(stdout,"%5.3f",
+					fuzzy(map_universe[k],&s_maps[i].sets[j]));
+						if (j < s_maps[i].nsets-1)
+							fprintf(stdout, ",");
+						else
+							fprintf(stdout, "\n");
+				}
+			}
+	}
+
+	G_free(map_universe);
+
+    for (i = 0; i < nmaps; ++i)
+	G_free(s_maps[i].sets);
+
+    G_free(s_maps);
+    G_free(s_rules);
+
+		exit(EXIT_SUCCESS);
+	
+}
+
+int set_cats(void)
+{
+struct Categories cats;
+float fmin, fmax;
+int cmin, cmax;
+int i, j;
+
+fmin=universe[0];
+fmax=universe[resolution];
+cmin=(int)universe[0];
+cmax=(int)universe[resolution];
+double tmp1, tmp2;
+float fuzzy_val=0;
+char buf[200];
+float rang;
+
+rang=(universe[0]+universe[1])/2.;
+Rast_read_cats(output, G_mapset(), &cats);
+Rast_set_cats_title("Result membership", &cats);
+
+	for (i=0;i<resolution;++i) {
+		strcpy(buf,"");
+		for (j=0; j<s_maps[output_index].nsets; ++j) { 
+			fuzzy_val=fuzzy(universe[i],&s_maps[output_index].sets[j]);
+				
+				if(universe[i]<s_maps[output_index].sets[1].points[0] ||
+					universe[i]>s_maps[output_index].sets[s_maps[output_index].nsets-2].points[3])
+			fuzzy_val=1;	
+				if (fuzzy_val>0.)
+			sprintf(buf,"%s %s=%2.2f", buf, s_maps[output_index].sets[j].setname,fuzzy_val);	
+		}
+
+		tmp1=(double)universe[i]-rang;
+		tmp2=(double)universe[i]+rang;
+		if(i==0) tmp1=(double)universe[i];
+		if(i==resolution) tmp2=(double)universe[i];
+		Rast_set_d_cat(&tmp1, &tmp2, buf, &cats);
+	}	
+Rast_write_cats(output, &cats);
+Rast_free_cats(&cats);
+return 0;
+}
+
+
+/* not in use yet
+void set_colors(void) {
+struct Colors colors;
+Rast_init_colors(&colors);
+Rast_add_d_color_rule(&val1, 255, 255, 255, &val2, 255, 255, 0, &colors);
+Rast_write_colors(output, G_mapset(), &colors);
+}
+*/

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/io.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/io.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/io.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,108 @@
+#include "local_proto.h"
+
+int open_maps(void)
+{
+
+    int i;
+    char *mapset;
+    struct Cell_head cellhd;
+
+			for (i = 0; i < nmaps; ++i) {
+		if (s_maps[i].output) {
+	s_maps[i].in_buf = NULL;
+	continue;
+		}
+	mapset = (char *)G_find_raster2(s_maps[i].name, "");
+
+	if (mapset == NULL)
+	    G_fatal_error(_("Raster map <%s> not found"), s_maps[i].name);
+
+	s_maps[i].cfd = Rast_open_old(s_maps[i].name, mapset);
+	Rast_get_cellhd(s_maps[i].name, mapset, &cellhd);
+
+	s_maps[i].raster_type = Rast_map_type(s_maps[i].name,mapset);
+	s_maps[i].in_buf = Rast_allocate_buf(s_maps[i].raster_type);
+			}
+	return 0;
+}
+
+int get_rows(int row)
+{
+	int i;
+
+    for (i = 0; i < nmaps; ++i) {
+			if (s_maps[i].output)
+		continue;
+	Rast_get_row(s_maps[i].cfd, s_maps[i].in_buf, row,
+	     s_maps[i].raster_type);
+		}
+  return 0;
+}
+
+int get_cells(int col)
+{
+    int i;
+    CELL c;
+    FCELL f;
+    DCELL d;
+
+    for (i = 0; i < nmaps; ++i) {
+
+	if (s_maps[i].output)
+	    continue;
+
+	switch (s_maps[i].raster_type) {
+
+	case CELL_TYPE:
+	    c = ((CELL *) s_maps[i].in_buf)[col];
+	    if (Rast_is_null_value(&c, CELL_TYPE))
+		return 1;
+	    else
+		s_maps[i].cell = (DCELL) c;
+	    break;
+
+	case FCELL_TYPE:
+	    f = ((FCELL *) s_maps[i].in_buf)[col];
+	    if (Rast_is_null_value(&f, FCELL_TYPE))
+		return 1;
+	    else
+		s_maps[i].cell = (DCELL) f;
+	    break;
+
+	case DCELL_TYPE:
+	    d = ((DCELL *) s_maps[i].in_buf)[col];
+	    if (Rast_is_null_value(&d, DCELL_TYPE))
+		return 1;
+	    else
+		s_maps[i].cell = (DCELL) d;
+	    break;
+	}
+    }				/* end for */
+
+    return 0;
+}
+
+int create_output_maps(void)
+{
+
+    STRING connector = "_";
+    int i;
+
+    m_outputs = (OUTPUTS *) G_malloc(nrules * sizeof(OUTPUTS));
+
+    for (i = 0; i < nrules; ++i) {
+	strcpy(m_outputs[i].output_name, output);
+	strcat(m_outputs[i].output_name, connector);
+	strcat(m_outputs[i].output_name, s_rules[i].outname);
+
+	if ((m_outputs[i].ofd =
+	     Rast_open_new(m_outputs[i].output_name, FCELL_TYPE)) < 0)
+	    G_fatal_error(_("Unable to create raster map <%s>"),
+			  m_outputs[i].output_name);
+
+	m_outputs[i].out_buf = Rast_allocate_f_buf();
+
+    }
+return 0;
+}
+

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,190 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+/*
+   PI2= PI/2
+   PI4= PI/4
+ */
+#ifndef PI2
+#define PI2 (2*atan(1))
+#endif
+
+#ifndef PI4
+#define PI4 (atan(1))
+#endif
+
+#define STACKMAX 50
+#define VARMAX 31
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+typedef char *STRING;
+
+typedef enum
+{
+    l_ZADEH,
+    l_PRODUCT,
+    l_DRASTIC,
+    l_LUKASIEWICZ,
+    l_FODOR,
+    l_HAMACHER
+} logics;
+
+typedef enum
+{
+    s_LINEAR,
+    s_SSHAPE,
+    s_JSHAPE,
+    s_GSHAPE
+} shapes;
+
+typedef enum
+{
+    s_BOTH,
+    s_LEFT,
+    s_RIGHT
+} sides;
+
+typedef enum
+{
+    i_MIN,
+    i_PROD
+} implications;
+
+typedef enum
+{
+    d_CENTEROID,
+    d_BISECTOR,
+    d_MINOFHIGHEST,
+    d_MAXOFHIGHEST,
+    d_MEANOFHIGHEST
+} defuzz;
+
+typedef enum
+{
+    E,				/* ERROR */
+    S,				/* SHIFT */
+    R,				/* REDUCE */
+    A				/* ACCEPT */
+} actions;
+
+typedef enum
+{
+    t_START,			/* { */
+    t_AND,			/* & */
+    t_OR,			/* | */
+    t_IS_NOT,			/* ~ */
+    t_IS,			/* = */
+    t_LBRC,			/* ( */
+    t_RBRC,			/* ) */
+    t_STOP,			/* } */
+    t_size,			/* number of tokens */
+    t_VAL			/* value a product of MAP and VARIABLE */
+} tokens;
+
+typedef struct
+{				/* membership definition */
+    char setname[21];
+    sides side;
+    float points[4];
+    shapes shape;
+    int hedge;
+    float height;
+} SETS;
+
+typedef struct
+{
+    char name[30];
+    int nsets;
+    int output;			/* is output map? */
+    RASTER_MAP_TYPE raster_type;
+    fpos_t position;
+    void *in_buf;
+    DCELL cell;
+    int cfd;			/* file descriptor */
+    SETS *sets;
+} MAPS;
+
+typedef struct
+{
+    DCELL *value;
+    SETS *set;
+    char oper;
+} VALUES;
+
+
+typedef struct /* stores queues with rules */
+{
+    char outname[20];
+    int output_set_index;
+    char parse_queue[STACKMAX][VARMAX]; /* original rule */
+    int work_queue[STACKMAX]; /* symbols of values and operators */
+    VALUES value_queue[STACKMAX]; /* pointers to values, operators and sets */
+    float weight;
+} RULES;
+
+typedef struct _outs
+{
+    char output_name[52];
+    int ofd;			/* output file descriptor */
+    FCELL *out_buf;
+} OUTPUTS;
+
+
+extern STRING var_name_file;
+extern STRING rule_name_file;
+extern STRING output;
+extern MAPS *s_maps;
+extern RULES *s_rules;
+extern OUTPUTS *m_outputs;
+extern float **visual_output;
+extern float *universe;
+extern float *antecedents;
+extern float *agregate;
+extern int nmaps, nrules, output_index, multiple, membership_only, coor_proc;
+extern int resolution;
+extern implications implication;
+extern defuzz defuzzyfication;
+extern logics family;
+
+extern char **rules;
+extern int HERE;
+
+int char_strip(char *buf, char rem);
+int char_copy(const char *buf, char *res, int start, int stop);
+int get_nsets(FILE * fd, fpos_t position);
+int get_universe(void);
+int set_cats(void);
+
+int parse_map_file(STRING file);
+int parse_rule_file(STRING file);
+int parser(void);
+int open_maps(void);
+int create_output_maps(void);
+int get_rows(int row);
+int get_cells(int col);
+
+int parse_sets(SETS * set, char buf[], const char mapname[]);
+int parse_rules(int rule_num, int n, char buf[]);
+void process_coors(char *answer);
+void show_membership(void);
+
+float implicate(void);
+float parse_expression(int n);
+float defuzzify(int defuzzification, float max_agregate);
+
+float f_and(float cellx, float celly, logics family);
+float f_or(float cellx, float celly, logics family);
+float f_not(float cellx, logics family);
+float fuzzy(FCELL cell, SETS * set);
+
+int parse(void);
+void display(void);
+

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,276 @@
+/* ***************************************************************************
+ *
+ * MODULE:       r.fuzzy.system
+ * AUTHOR(S):    Jarek Jasiewicz <jarekj amu.edu.pl>
+ * PURPOSE:      Full fuzzy logic standalone classification system with few fuzzy logic families 
+ *                                                       implication and defuzzification and methods.
+ * COPYRIGHT:    (C) 1999-2010 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *************************************************************************** */
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+STRING var_name_file;
+STRING rule_name_file;
+STRING output;
+MAPS *s_maps;
+RULES *s_rules;
+OUTPUTS *m_outputs;
+float **visual_output;
+float *universe;
+float *antecedents;
+float *agregate;
+int nmaps, nrules, output_index, multiple, membership_only, coor_proc;
+int resolution;
+implications implication;
+defuzz defuzzyfication;
+logics family;
+
+char **rules;
+int HERE;
+
+int main(int argc, char **argv)
+{
+    struct Option *file_vars,
+	*file_rules,
+	*par_family,
+	*par_resolution,
+	*par_defuzzify, *par_implication, *in_coor_opt, *opt_output;
+
+    struct History history;
+
+    struct GModule *module;
+    struct Flag *out_multiple, *out_membership;
+
+    int nrows, ncols;
+    int row, col;
+    int outfd;
+    float tmp;
+    FCELL *out_buf;
+
+    int i, j, n;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("raster, fuzzy logic");
+    module->description =
+        _("xxxx");
+
+    file_vars = G_define_standard_option(G_OPT_F_INPUT);
+    file_vars->key = "maps";
+    file_vars->required = YES;
+    file_vars->description = _("Name of fuzzy variable file");
+
+    file_rules = G_define_standard_option(G_OPT_F_INPUT);
+    file_rules->key = "rules";
+    file_rules->required = NO;
+    file_rules->description = _("Name of rules file");
+
+    par_family = G_define_option();
+    par_family->key = "family";
+    par_family->type = TYPE_STRING;
+    par_family->options = "Zadeh,product,drastic,Lukasiewicz,Fodor,Hamacher";
+    par_family->answer = "Zadeh";
+    par_family->required = YES;
+    par_family->description = _("Fuzzy logic family");
+    par_family->guisection = _("Advanced options");
+
+    par_defuzzify = G_define_option();
+    par_defuzzify->key = "defuz";
+    par_defuzzify->type = TYPE_STRING;
+    par_defuzzify->options = "centroid,bisector,min_of_highest,max_of_highest,mean_of_highest";
+    par_defuzzify->answer = "bisector";
+    par_defuzzify->required = YES;
+    par_defuzzify->description = _("Defuzzyfication method");
+    par_defuzzify->guisection = _("Advanced options");
+
+    par_implication = G_define_option();
+    par_implication->key = "imp";
+    par_implication->type = TYPE_STRING;
+    par_implication->options = "minimum,product";
+    par_implication->answer = "minimum";
+    par_implication->required = YES;
+    par_implication->description = _("Implication method");
+    par_implication->guisection = _("Advanced options");
+
+    par_resolution = G_define_option();
+    par_resolution->key = "res";
+    par_resolution->type = TYPE_INTEGER;
+    par_resolution->answer = "100";
+    par_resolution->required = YES;
+    par_resolution->description = _("Universe resolution");
+    par_resolution->guisection = _("Advanced options");
+
+    in_coor_opt = G_define_option();	/* input coordinates de outlet */
+    in_coor_opt->key = "coors";
+    in_coor_opt->type = TYPE_STRING;
+    in_coor_opt->key_desc = "x,y";
+    in_coor_opt->answer = NULL;
+    in_coor_opt->required = NO;
+    in_coor_opt->multiple = NO;
+    in_coor_opt->description =
+	"Coordinate of cell for detail data (print end exit)";
+    in_coor_opt->guisection = _("Visual Output");
+
+    out_membership = G_define_flag();
+    out_membership->key = 'o';
+    out_membership->description =
+	_("Print only membership values and exit");
+		out_membership->guisection = _("Visual Output");
+
+    out_multiple = G_define_flag();
+    out_multiple->key = 'm';
+    out_multiple->description =
+	_("Create addational fuzzy output maps for every rule");
+
+
+    opt_output = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_output->description = _("Name of output file");
+		opt_output->required = NO;
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    var_name_file = file_vars->answer;
+    rule_name_file = file_rules->answer;
+    output = opt_output->answer;
+    multiple = (out_multiple->answer != 0);
+    membership_only = (out_membership->answer != 0);
+    coor_proc = (in_coor_opt->answer) ? 1 : 0;
+
+			if(!membership_only & (!output | !rule_name_file))
+		G_fatal_error(_("for standard analysis both output and rule file are required"));
+
+    resolution = atoi(par_resolution->answer);
+    if (resolution < 10)
+	G_fatal_error(_("Universe resolution too small, choose greater value"));
+    if (resolution > 500)
+	G_warning(_("Universe resolution is very high, computation may take a long time"));
+
+    if (!strcmp(par_family->answer, "Zadeh"))
+	family = l_ZADEH;
+    else if (!strcmp(par_family->answer, "product"))
+	family = l_PRODUCT;
+    else if (!strcmp(par_family->answer, "drastic"))
+	family = l_DRASTIC;
+    else if (!strcmp(par_family->answer, "Lukasiewicz"))
+	family = l_LUKASIEWICZ;
+    else if (!strcmp(par_family->answer, "Fodor"))
+	family = l_FODOR;
+    else if (!strcmp(par_family->answer, "Hamacher"))
+	family = l_HAMACHER;
+
+    if (!strcmp(par_implication->answer, "minimum"))
+	implication = i_MIN;
+    else if (!strcmp(par_implication->answer, "product"))
+	implication = i_PROD;
+
+    if (!strcmp(par_defuzzify->answer, "centroid"))
+	defuzzyfication = d_CENTEROID;
+    else if (!strcmp(par_defuzzify->answer, "bisector"))
+	defuzzyfication = d_BISECTOR;
+    else if (!strcmp(par_defuzzify->answer, "min_of_highest"))
+	defuzzyfication = d_MINOFHIGHEST;
+    else if (!strcmp(par_defuzzify->answer, "max_of_highest"))
+	defuzzyfication = d_MAXOFHIGHEST;
+    else if (!strcmp(par_defuzzify->answer, "mean_of_highest"))
+	defuzzyfication = d_MEANOFHIGHEST;
+
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+		
+		parse_map_file(var_name_file);
+			if (membership_only)
+    show_membership();
+    
+		parse_rule_file(rule_name_file);
+    get_universe();
+    open_maps();
+	
+		antecedents = (float *)G_malloc(nrules * sizeof(float));
+		agregate = (float *)G_calloc(resolution, sizeof(float));
+			if (coor_proc)
+		process_coors(in_coor_opt->answer);
+
+   outfd = Rast_open_new(output, FCELL_TYPE);
+   out_buf = Rast_allocate_f_buf();
+
+    if (multiple)
+	create_output_maps();
+  
+		G_message("Calculate...");
+
+	for (row = 0; row < nrows; ++row) {
+		G_percent(row, nrows, 2);
+		get_rows(row);
+		for (col = 0; col < ncols; ++col) {
+	    if (get_cells(col)) {
+		Rast_set_f_null_value(&out_buf[col], 1);
+
+		if (multiple) {
+		    for (i = 0; i < nrules; ++i)
+			Rast_set_f_null_value(&m_outputs[i].out_buf[col], 1);
+		}
+	    }
+	    else {
+		out_buf[col] = implicate();
+			if (out_buf[col] == -9999)
+		Rast_set_f_null_value(&out_buf[col], 1);
+
+		if (multiple) {
+		    for (i = 0; i < nrules; ++i)
+			m_outputs[i].out_buf[col] = antecedents[i];
+		}
+	    }
+	}
+	Rast_put_row(outfd, out_buf, FCELL_TYPE);
+
+			if (multiple) 
+	  for (i = 0; i < nrules; ++i)
+	Rast_put_row(m_outputs[i].ofd, m_outputs[i].out_buf, FCELL_TYPE);
+    }
+  G_percent(row, nrows, 2);
+		
+  G_message("Close...");
+
+		
+
+  Rast_close(outfd);
+  Rast_short_history(output, "raster", &history);
+  Rast_command_history(&history);
+  Rast_write_history(output, &history);
+	set_cats();
+		/* free */
+			for (i = 0; i < nmaps; ++i) {
+		G_free(s_maps[i].sets);
+				if (s_maps[i].output)
+	    continue;
+		G_free(s_maps[i].in_buf);
+		Rast_close(s_maps[i].cfd);
+			}
+  G_free(antecedents);
+  G_free(agregate);
+  G_free(out_buf);
+  G_free(s_maps);
+  G_free(s_rules);
+   
+    if (multiple)
+	for (i = 0; i < nrules; ++i) {
+	  G_free(m_outputs[i].out_buf);
+	  Rast_close(m_outputs[i].ofd);
+	  Rast_short_history(m_outputs[i].output_name, "raster", &history);
+	  Rast_command_history(&history);
+	  Rast_write_history(m_outputs[i].output_name, &history);
+	}
+
+   G_message("Done!");
+    exit(EXIT_SUCCESS);
+
+}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/map_parser.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/map_parser.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/map_parser.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,222 @@
+#include "local_proto.h"
+
+int parse_map_file(STRING file)
+{
+    FILE *fd;
+    int line = 0;
+    char buf[500];
+    STRING mapset;
+    char map[30];
+    int nmaps2 = 0, nsets = 0;
+    fpos_t init;
+    fpos_t position;
+    int set_num;
+
+    int i;
+
+    fd = fopen(file, "r");
+    if (!fd)
+	G_fatal_error(_("Cannot open map file '%s'"), file);
+
+    fgetpos(fd, &init);
+
+    nmaps = 0;
+    /* number of maps */
+    while (fgets(buf, sizeof buf, fd)) {
+	G_strip(buf);
+	if (*buf != '%')
+	    continue;
+	nmaps++;
+    }
+    s_maps = (MAPS *) G_malloc(nmaps * sizeof(MAPS));
+    fsetpos(fd, &init);		/* reset position */
+
+    while (fgets(buf, sizeof buf, fd)) {
+	line++;
+
+	G_strip(buf);
+	if (*buf == '#' || *buf == 0 || *buf == '\n')
+	    continue;
+
+	if (*buf != '%' && *buf != '$')
+	    G_fatal_error(_("Wrong syntax at line %d: line must start with <#>, <%> or <$> or be empty line"),
+			  line);
+
+	if (*buf == '%') {
+
+	    fgetpos(fd, &position);
+
+	    sscanf(buf, "%[^\n]", map);
+	    char_strip(map, '%');
+	    G_strip(map);
+	    mapset = (STRING)G_find_raster2(map, "");
+
+	    if (mapset == NULL && strcmp(map, "_OUTPUT_"))
+		G_fatal_error(_("Raster map <%s> not found"), map);
+
+				if (!strcmp(map, "_OUTPUT_")) {
+			strcpy(s_maps[nmaps2].name, output);
+			s_maps[nmaps2].output=1;
+				} else {
+	    strcpy(s_maps[nmaps2].name, map);
+	    s_maps[nmaps2].output=0;
+				}
+	    s_maps[nmaps2].position = position;
+	    s_maps[nmaps2].nsets = get_nsets(fd, position);
+	    
+
+	    if (!s_maps[nmaps2].nsets)
+		G_warning(_("map <%s> has no rules"), s_maps[nmaps2].name);
+
+	    if (s_maps[nmaps2].nsets)
+		s_maps[nmaps2].sets =
+		    (SETS *) G_malloc(s_maps[nmaps2].nsets * sizeof(SETS));
+
+	    set_num = 0;
+	    while (fgets(buf, sizeof buf, fd)) {
+		G_strip(buf);
+
+		if (*buf == '#' || *buf == 0 || *buf == '\n')
+		    continue;
+		if (*buf == '%')
+		    break;
+
+		parse_sets(&s_maps[nmaps2].sets[set_num++], buf,
+			   s_maps[nmaps2].name);
+
+	    }
+	    fsetpos(fd, &position);
+
+	    if (nmaps2++ > nmaps)
+		G_fatal_error(_("number of maps do not match"));
+
+	}
+
+    }				/* end while */
+
+    fclose(fd);
+    return 0;
+}
+
+
+int parse_sets(SETS * set, char buf[], const char mapname[])
+{
+
+    char tmp[20];
+    int i;
+
+    char_strip(buf, '$');
+
+    {				/* check length of fuzzy value (cannot be longer than 20) */
+	sscanf(buf, "%[^{] %[^\n]", tmp, buf);
+	G_strip(tmp);
+
+	if (strlen(tmp) < 21)
+	    strcpy(set->setname, tmp);
+	else
+	    G_fatal_error(_("Map: <%s>, Membership: <%s>: Value name cannot be longer than 20 chars, but has %d chars"),
+			  mapname, tmp, (int)strlen(tmp));
+    }				/* check length of fuzzy value */
+
+    {				/* check if side is valid (both,left,right) */
+	int done = 1;
+	STRING sides[] = { "both", "left", "right" };
+
+	char_strip(buf, '{');
+	sscanf(buf, "%[^;] %[^\n]", tmp, buf);
+
+	done = 0;
+	for (i = 0; i < 3; ++i)
+	    if (strcmp(tmp, sides[i]) == 0) {
+		done = 1;
+		break;
+	    }
+
+	if (done)
+	    set->side = i;
+	else
+	    G_fatal_error(_(" Map: <%s>, Membership: <%s>:  <side> parameter must be:  <left,right,both> but is: <%s>"),
+			  mapname, set->setname, tmp);
+    }				/* end check if side is valid */
+
+
+    {				/* check number of points and order.  Point number limited to 10 chars including coma */
+	char p[11];
+	int npoints;
+
+	char_strip(buf, ';');
+	sscanf(buf, "%[^;] %[^\n]", tmp, buf);
+	char_strip(tmp, ';');
+
+	npoints = set->side ? 2 : 4;
+
+	for (i = 0; i < npoints; ++i) {
+	    sscanf(tmp, "%[^,] %[^\n]", p, tmp);
+
+	    if (tmp[0] != ',' && i < (npoints - 1))
+		G_fatal_error(_("Map: <%s>, Variable: <%s>: Require %d points but has %d"),
+			      mapname, set->setname, npoints, i + 1);
+
+	    if (sscanf(p, "%f", &set->points[i]) != 1)
+		G_fatal_error(_("Map: <%s>, Variable: <%s>: Points must be numeric  but is: %s or space between '-' and digit"),
+			      mapname, set->setname, p);
+
+	    char_strip(tmp, ',');
+
+	    if (i > 0 && (set->points[i] < set->points[i - 1]))
+		G_fatal_error(_("Map: <%s>, Membership: <%s>: Points sequence must be non-declining"),
+			      mapname, set->setname);
+	}
+
+    }				/* check number of points and order */
+
+
+    {				/* check if shape is valid (linear,sshaped,jshaped,gshaped) */
+	int done = 1;
+	STRING shapes[] = { "linear", "sshaped", "jshaped", "gshaped" };
+
+	char_strip(buf, ';');
+	sscanf(buf, "%[^;] %[^\n]", tmp, buf);
+
+	done = 0;
+	for (i = 0; i < 4; ++i)
+	    if (strcmp(tmp, shapes[i]) == 0) {
+		done = 1;
+		break;
+	    }
+
+	if (done)
+	    set->shape = i;
+	else
+	    G_fatal_error(_(" Map: <%s>, Variable: <%s>:  <shape> parameter must be: <linear,sshaped,jshaped,gshaped> but is: <%s>"),
+			  mapname, set->setname, tmp);
+    }				/* end check if shape is valid */
+
+
+    {				/* check if hedge is valid  (integer) */
+	char_strip(buf, ';');
+	sscanf(buf, "%[^;] %[^\n]", tmp, buf);
+
+	if (sscanf(tmp, "%d", &set->hedge) != 1)
+	    G_fatal_error(_("Map: <%s>, variable: <%s>: Hedge must be numeric  but is: %s or space between '-' and digit"),
+			  mapname, set->setname, tmp);
+
+    }				/* end check if hedge is valid */
+
+
+    {				/* check if height is valid  (float 0-1) */
+	char_strip(buf, ';');
+	sscanf(buf, "%[^}] %[^\n]", tmp, buf);
+
+	if (sscanf(tmp, "%f", &set->height) != 1)
+	    G_fatal_error(_("Map: <%s>, Variable: <%s>: Height must be  non-negative numeric lesser than 1 but is: %s"),
+			  mapname, set->setname, tmp);
+
+	if (set->height <= 0 || set->height > 1)
+	    G_fatal_error(_("Map: <%s>, Variable: <%s>: Height must be  non-negative numeric lesser than 1 but is: %f"),
+			  mapname, set->setname, set->height);
+
+    }				/* end check if height is valid */
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/r.fuzzy.system.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/r.fuzzy.system.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/r.fuzzy.system.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,320 @@
+<h2>OPTIONS</h2>
+
+<dl>
+<dt><b>maps</b></dt>
+<dd>A text file containing maps name and  fuzzy sets connected with map
+definition. Maps in text file must exist on a search path, except the output
+map. The name of output map name is the output name parameter. In map file
+outmput map is marked by special name <b>_OUTPUT_</b>  If maps are in different
+mapsets the name require @. Map names in database cannot contain following
+symbols: <b> %,$ and #</b>. Every map name must start with map name
+identifier:<b> %</b>. Every set definition connected with cetrain map must
+follow the map name and must start with set identifier :<b> $</b>. The set
+definition must be in braces { } and requires parameters separated by semicolon.
+Any whitespaces like spaces, tabs, empty lines are allowed and may used to
+visual format of rule file.
+
+<pre>$ set_name {side; points; boundary_shape; hedge; height }</pre>
+<ul>
+<li><b>set_name</b>: Any name of the fuzzy set. Must not contain symbols: <i>
+%,$ and #</i>
+<li><b>side</b>: Option indicate if set is fuzzified of both sides (both), left
+or right side. Available: <i>both, left, right</i>. 
+<li><b>points</b>: A list containing 4 (A,B,C,D) or 2 A,B) points separated by
+comma. Points definine  location of sets of boundaries. Points may not to be in
+map range, but it may lead to only 0 o 1 membership for the whole map. For
+"both" side parameters range between A and D defines base, but range between B
+and C core of the fuzzy set. Between A and B and C and D are set's boundaries.
+If side is "both" it require 4 points, else 2 points. Points values must be
+not-decreasing.
+<li><b>shape</b>: Parameter definied the shape of the fuzzy boundary. Available:
+<i>sshaped, linear, jshaped, gshaped</i>. The same boundaires are appled to 
+both sides of fuzzy set.
+<li><b>hedge</b>: Shape modifier the positive number means dilatation (power the
+fuzzy set by 2) the negative means concetration (square root of fuzzy set). The
+number means number of dilatation/concetration applied on fuzzy set.
+<li><b>height</b>: Height modifier. Range from 0 to 1. The  value 1 and indicate
+full membership beteen points B and C. If height is lesser than one the maximum
+memebrship is equal to height.
+</ul>
+<p>An example of fuzzy sets definiton:
+<pre>$ moderate {both; 90,100,120,130; sshaped; 0; 1}</pre>
+
+<b>Special notes about sets definition for output map:</b><br>
+These sets shall be created as triangular (both sides) sets with linear
+boundaries, without hedge and height modifiers:
+<pre>$ moderate {both; 0,20,20,40; linear; 0; 1}</pre>
+</dd>
+
+<dt><b>rules</b></dt>
+<dd>A text file containing rules for classification.Th typical fuzzy rule
+consists of one or more antecedents and one consequent:
+
+<pre>IF elev IS high AND distance IS low THEN probability IS small
+
+where:
+antecetends: elev IS high; distance IS low
+consequent: probability IS small
+</pre>
+
+The rule file has his own syntax. Because module creates only one result map,
+the map name is ommited. Every rule starts with $ and consist of consequent name
+and antecedents in braces { }. All maps and sets used in atecednets must be
+included in the maps file. At the begining of the calculation program checks if
+all names and sets are included in maps file. Names of the rules must be same as
+sets names of the output map. The rules file use following symbols:
+<ul>
+<li>IS is symbolised by <b>=</b>
+<li>IS NOT is symbolised by <b>~</b>
+<li>AND is symbolised by <b>&</b>
+<li>OR is symbolised by <b>|</b>
+<li>To  specify the order of operators must use parentheses <b>()</b>.
+</ul>
+
+
+<p>An example of fuzzy rules definiton:
+<pre>
+$ small {distance = high & elev = high}
+</pre>
+
+</dd>
+</dl>
+<h2>ADVANCED OPTIONS</h2>
+In most cases default options shoud not be changed.
+<dl>
+<dt><b>family</b></dt>
+<dd>AND and OR operations in fuzzy logic are made with T-norms, T-conorms.
+T-norms, T-conorms are a generalization of the two-valued logical conjunction
+and  disjunction  used by boolean logic, for fuzzy logics. Because there is more
+than one possible generalisation of logial operations, r.fuzzy.system provides 6
+most popular families for fuzzy operations:
+<ul>
+<li><b>Zadeh</b> with minimum (Godel) t-norm and maximum T-conorm;
+<li><b>product</b> with product T-norm and probabilistic sum as T-conorm;
+<li><b>drastic</b> with drastic T-norm and drastic T-conorm;
+<li><b>Lukasiewicz</b> with Lukasiewicz T-norm and bounded sum as a T-conorm;
+<li><b>Fodor</b> with nilpotent minimum as T-norm and nilpotent maximum as
+T-conorm;
+<li><b>Hamacher</b> (simplified) with Hamacher product as T-norm and Einstein
+sum as T-conorm;
+</ul>
+<p>
+<TABLE cellspacing=4>
+<TR><TH>Family</TH><TH> T-NORM (AND) </TH><TH>T CONORM (OR) </TH></TR>
+<TR><TD>ZADEH</TD><TD> MIN(x,y)</TD><TD>MAX(x,y)</TD></TR>
+<TR><TD>PRODUCT</TD><TD>	x*y	</TD><TD>x + y -x * y</TD></TR>
+<TR><TD>DRASTIC	</TD><TD>IF MAX(x, y) == 1 THEN MIN(x, y) ELSE 0
+</TD><TD>IF (MIN(x, y) == 0) THEN MAX(x, y) ELSE 1</TD></TR>
+<TR><TD>LUKASIEWICZ</TD><TD>	MAX((x+y-1),0)</TD><TD>	MIN((x+y),1)</TD></TR>
+<TR><TD>FODOR	</TD><TD>IF (x+y)>1 THEN MIN(x,y) ELSE 0	</TD><TD>IF
+(x+y<1) THEN MAX(x,y) ELSE 1</TD></TR>
+<TR><TD>HAMACHER</TD><TD>	IF (x==y==0) THEN 0 ELSE
+(x*y)/((x+y)-x*y)</TD><TD>	(x+y)/(1+x*y)</TD></TR>
+</TABLE>
+</dd>
+<dt><b>imp: implication </b></dt>
+<dd>Imlication determines the method of reshapening of consequents (fuzzy set)
+by antecedents (single value) : 
+<ul>
+<li><b>minimum</b> means the lowest value of the antecedtents and output set
+definition. It usually creates trapezoidal consequent set definition.
+<li><b>product</b> means the multiplication of the antecedtents and output set
+definition. It usually creates triangular consequent set definition.
+</ul>
+</dd>
+<dt><b>defuzz: deffuzyfication method</b></dt>
+<dd>Before deffuzification all consequents are agregated into one fuzzy set.
+Defuzzification is the process of conversion of aggregated fuzzy set into one
+crisp value. The r.fuzzy.system provides 5 methods of deffuzyfication:
+<ul>
+<li><b>centroid</b> center of mass of the fuzzy set (in practise weighted mean);
+<li><b>bisector</b> a value which divide fuzzy set on two parts of equal area;
+<li><b>min</b> min (right limit) of highest part of the set;
+<li><b>mean</b> mean (center) of highest part of the set;
+<li><b>max</b> max (left limit) of highest part of the set;
+</ul>
+</dd>
+<dt><b>res: universe resolution</b></dt>
+<dd>The universe is an interval between the lowest and highest values of
+consequent and agregated fuzzy sets. The resolution provides number of elements
+of these fuzzy sets. The minimum and maximum for univese is taken from the
+minimal and maximal values of fuzzy set definition of output map Because it has
+strong impact on computation time and precision of deffuzification, values lower
+than 30 may impact on precision of final result, but values above 200 may slow
+down computation time.
+</dd>
+</dl>
+<h2>VISUAL OUTPUT</h2>
+<dl>
+<dt><b>coordinates</b></dt>
+<dd>Coordinates of points for which output: universe, all consequents sets and
+agregate set. It is useful for visual presentation or detail analysis of fuzzy
+rules behaviour. In that cases calculations are peroforemd n=only for selected
+point.</dd>
+<dt><b>membership only flag</b></dt>
+<dd>Prints for all maps sat of values in map range (map universe) and values of
+fuzzy sets (linguistic values). Number of values is taken from resolution
+(default 100). This option is useful for visual control fuzzy set definitions
+for evrey map.</dd>
+</dl>
+
+<h2>OUTPUTS</h2>
+<dl>
+<dt><b>output</b></dt>
+<dd>Map containing deffuzified values. Map is always of type FCELLS and contains
+values defined in output universe. The output name must be the same as one of
+maps in maps definition file.
+</dd>
+<dt><b>multipe output flag</b></dt>
+<dd>This flag is used to create fuzzified maps for every rule. The name of the
+map consist of otput map name, '_' and rule name (for example: output=probs and
+rule name high, the map name: probs_high). Values of maps ranges from 0  to 1.
+If map with such name exists will be overwritten without warning.
+</dd>
+</dl>
+<h2>NOTES</h2>
+<h4>Calculation of boundary shape</h4>
+Depending on type of the boundary different equation are used to determine its
+shape:
+<p>
+<b>Linear:</b> the membership is calculated according following equation:<br>
+
+<pre><code>
+value  <=  A -> x = 0
+A< value > B -> x = (value-A)/(B-A)
+B <= value >= C -> x = 1
+C< value > D -> x = (D-value)/(D-C)
+value  >=  D -> x = 0
+</code></pre>
+<b>S-shaped, G-shaped and J shaped:</b>  use following equation to sommoth
+boundary:
+<pre><code>
+sin(x * Pi/2)^2 (for S-shaped)
+tan(x * Pi/4)^2 (for J-shaped)
+tan(x * Pi/4)^0.5 (for G-shaped)
+
+where:
+x current fuzzy value
+A,B,C,D inflection point,
+</code></pre>
+
+<h2>EXAMPLE</h2>
+<p>
+Fuzzy sets are sets whose elements have degrees of membership. Zadeh (1965)
+introduced Fuzzy sets as an extension of the classical notion of set. Classical 
+membership of elements in a set are binary terms: an element either belongs or
+does not belong to the set. Fuzzy set theory use the gradual membership of
+elements in a set. A membership function use values in the real unit interval
+[0, 1]. Classical sets, are special cases of the membership functions of fuzzy
+sets and only take values 0 or 1. Classical sets are in fuzzy set theory usually
+called crisp sets. The fuzzy set theory can be used in a wide range of domains
+in which information is  imprecise, such as most of the GIS operations.
+<p>
+Suppose we want to determine the flood risk on some area (Spearfish dataset)
+using two maps: distance to streams and elevation above streams. We can write
+some common sense rules:
+<pre>
+IF elevation IS low AND distance IS near THEN risk IS veryprobable
+IF elevation IS low OR distance IS near THEN risk IS probable
+IF elevation IS high AND distance IS far THEN risk IS unprobable
+</pre>
+In clasical boolean sense, we would taken some limits of ideas "near" "far" etc,
+but what about walues near the limit? The fuzzy set uses partial memberships
+which abolish these restrictions. In that sense to set "near" belongs all areas
+with distance no more than 100 m with full membership and from 100 to 200 m with
+partial membership greater than 0. Over 200 m we can assume that is not near.
+This allow to formulate fuzzy rules for distance map:
+<pre>
+near: BELOW 100 = 1; FROM 100 TO 200 = {1 TO 0}; ABOVE 200 = 0;
+</pre>
+
+To recive final map program calculate partial fuzzy set for all rules and next
+agregate it into one fuzzy set. These fuzzy sets are created on value sequence
+called universe. Every set has the number of elements equal to universe
+resolution. Such set cannot be stored as map so finally is deffuzified with
+method choosen by user.
+<p>
+First we need two maps created with r.stream package:
+
+<pre>
+r.stream.extract elevation=elevation.10m at PERMANENT threshold=2000
+stream_rast=streams direction=dirs 
+r.stream.order stream=streams dir=dirs horton=horton
+r.mapcalc "horton3=if(horton>2,horton,null())"
+r.stream.distance stream=streams dir=dirs dem=elevation.10m method=downstream
+distance=distance elevation=elevation 
+</pre>
+
+Next, to perform analysis we need two files: one with definition of map used in
+analysis and definition of fuzzy sets for every map, and second with fuzzy
+rules. For this example:
+
+<p>MAPS
+<pre>
+#flood.map
+	%elevation
+$ low {right; 2,6; sshaped; 0; 1}
+$ high {left; 2,6; sshaped; 0; 1}
+	%distance
+$ near {right; 40,80; sshaped; 0; 1}
+$ far {left; 40,80; sshaped; 0; 1}
+#output map
+	%flood
+$ unprob {both; 0,20,20,40; linear; 0;1}
+$ prob {both; 20,40,40,60; linear; 0;1}
+$ veryprob {both; 40,60,60,80; linear; 0;1}
+
+</pre>
+<p>RULES:
+<pre>
+#flood.rul
+$ unprob {elevation = high & distance = far}
+$ prob {distance = near | elevation = low}
+$ veryprob {distance = near & elevation = low}
+</pre>
+
+finally we need run r.fuzzy.system:
+<pre>
+r.fuzzy.system maps=flood.map rules=flod.rul output=flood 
+</pre>
+
+Resulting map should look like this below. Yellow color means no risk, red high
+risk, green, blue end so on moderate risk.
+<CENTER><img src=f_result.png border=1></CENTER><br>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.fuzzy.html">r.fuzzy</a>,
+<a href="r.fuzzy.logic.html">r.fuzzy.logic</a>,
+<a href="r.fuzzy.set.html">r.fuzzy.set</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+</em>
+
+
+
+<h2>REFERENCES</h2>
+
+Zadeh, L.A. (1965). "Fuzzy sets". Information and Control 8 (3): 338–353.
+doi:10.1016/S0019-9958(65)90241-X. ISSN 0019-9958.<p>
+
+Novák, Vilém (1989). Fuzzy Sets and Their Applications. Bristol: Adam Hilger.
+ISBN 0-85274-583-4.<p>
+
+Klir, George J.; Yuan, Bo (1995). Fuzzy sets and fuzzy logic: theory and
+applications. Upper Saddle River, NJ: Prentice Hall PTR. ISBN 0-13-101171-5.<p>
+
+Klir, George J.; St Clair, Ute H.; Yuan, Bo (1997). Fuzzy set theory:
+foundations and applications. Englewood Cliffs, NJ: Prentice Hall. ISBN
+0133410587.<p>
+
+Meyer D, Hornik K (2009a). \Generalized and Customizable Sets in R." Journal of
+Statistical Software, 31(2), 1{27. URL http://www.jstatsoft.org/v31/i02/.<p>
+
+Meyer D, Hornik K (2009b). sets: Sets, Generalized Sets, and Customizable Sets.
+R~package version~1.0, URL http://CRAN.R-project.org/package=sets.<p>
+
+<h2>AUTHOR</h2>
+Jarek  Jasiewicz
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/rule_parser.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/rule_parser.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/rule_parser.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,309 @@
+#include "local_proto.h"
+
+int parse_rule_file(STRING file)
+{
+    FILE *fd;
+    char buf[1000];
+    char tmp[30];
+    STRING mapset;
+    char map[30];
+    fpos_t init;
+    int rule_num = 0;
+    int n = 0, i;
+
+    fd = fopen(file, "r");
+    if (!fd)
+	G_fatal_error(_("Cannot open rules file '%s'"), file);
+
+    fgetpos(fd, &init);
+
+    while (fgets(buf, sizeof buf, fd)) {
+	G_strip(buf);
+	if (*buf != '$')
+	    continue;
+	nrules++;
+    }
+
+    s_rules = (RULES *) G_malloc((nrules) * sizeof(RULES));
+    rules = (char **)G_malloc((nrules) * sizeof(char *));
+    for (i = 0; i < nrules; ++i)
+	rules[i] = (char *)G_malloc(21 * sizeof(char));
+
+    fsetpos(fd, &init);		/* reset position */
+
+    for (n = nmaps; n > 0; --n)
+	if (!strcmp(s_maps[n - 1].name, output))
+	    break;		/*max index of output map */
+
+    if (n == 0)
+	G_fatal_error(_("No defininition for output map: <%s> in map file"),
+		      output);
+
+    while (fgets(buf, sizeof buf, fd)) {
+	G_strip(buf);
+	if (*buf != '$')
+	    continue;
+
+	parse_rules(rule_num++, n, buf);
+
+	/* next rule */
+    }
+
+			for (i = 0; i < nrules; ++i)
+		G_free(rules[i]);
+		G_free(rules);
+    fclose(fd);
+    return 0;
+
+}				/* END parse_rule_file */
+
+
+
+int parse_rules(int rule_num, int n, char buf[])
+{
+
+    int i, j, l, o;
+    int done = 1;
+    int stack_top;
+    char tmp[30];
+    char opr[] = { '=', '&', '|', '~', '(', ')', '{', '}' };
+
+    i = j = stack_top = 0;	/* variables of the while loop */
+    char_strip(buf, '$');
+
+
+    {				/* check the name of fuzzy value (must be defined in rules) */
+	int s, p;
+
+	sscanf(buf, "%[^{] %[^\n]", tmp, buf);
+	G_strip(buf);
+	G_strip(tmp);
+
+		for (p = 0; p <= rule_num; ++p)
+	strcpy(rules[p],"");
+	
+	done = 1;
+	for (s = 0; s <= s_maps[n - 1].nsets; ++s) {	/* output map */
+
+	    if (!strcmp(s_maps[n - 1].sets[s].setname, tmp)) {
+
+		for (p = 0; p <= rule_num; ++p)	/* check if values are unique */
+		    if (!strcmp(tmp, rules[p]))
+			G_fatal_error(_("Variable value <%s> exist, Variable values must be unique"),
+				      tmp);
+
+		strcpy(rules[rule_num], tmp);
+		done = 0;
+		break;
+	    }
+	}
+	if (done)
+	    G_fatal_error(_("Output map do not have variable value <%s>"),
+			  tmp);
+	strcpy(s_rules[rule_num].outname, tmp);
+	s_rules[rule_num].output_set_index = s;
+
+    }				/* check the name of fuzzy value */
+
+    /* ******************************************************************* */
+
+    {				/* parse rule expression and create parse stack */
+
+
+	do {
+	    for (o = 0; o < (sizeof opr); ++o) {
+		if (buf[i] == opr[o]) {
+		    char_copy(buf, tmp, j, i);
+		    if (i > 0) {
+			char_strip(tmp, buf[j]);
+			s_rules[rule_num].parse_queue[stack_top][0] = buf[j];
+			s_rules[rule_num].parse_queue[stack_top++][1] = '\0';
+			G_strip(tmp);
+		    }
+		    if (strlen(tmp))	/* is not blank */
+			strcpy(s_rules[rule_num].parse_queue[stack_top++],
+			       tmp);
+
+		    j = i;
+		    break;
+		}
+	    }
+	    if (i > 999)
+		G_fatal_error(_("rule string is too long or lack of closing element"));
+
+	} while (buf[i++] != '}');	/* rule has been read */
+
+	strcpy(s_rules[rule_num].parse_queue[stack_top++], "}");	/* add closing element only if OK */
+
+
+    }				/* end parse rule expression and create parse stack */
+
+    /* ******************************************************************* */
+
+
+/*    {				 adding weight: not implemented yet
+
+	char local[900];
+	char weight[10];
+
+	sscanf(buf, "%[^}] %[^;]", local, weight);
+	char_strip(weight, '}');
+	G_strip(weight);
+	if (strlen(weight) == 0)
+	    strcpy(weight, "1");
+	s_rules[rule_num].weight = atof(weight);
+	if (s_rules[rule_num].weight <= 0.)
+	    G_fatal_error(_("Weight must be grater than 0 or non-number character"));
+
+    } */
+
+    {				/* check if rule syntax is proper and map names and vars values exist */
+	int k;
+	int work_queue_pos = 0;
+	int lbrc = 0, rbrc = 0;	/* left and right braces */
+
+	done = 1;
+	for (i = 0; i < stack_top; ++i) {	/* most external loop */
+	    if (*s_rules[rule_num].parse_queue[i] == '{') {
+
+		s_rules[rule_num].work_queue[work_queue_pos] = t_START;
+
+		if (i > 0)
+		    G_fatal_error(_("line %d Syntax error near <%s %s>"),
+				  rule_num + 1,
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i]);
+
+		work_queue_pos++;
+		continue;
+	    }			/* END { */
+
+	    if (*s_rules[rule_num].parse_queue[i] == '=' || *s_rules[rule_num].parse_queue[i] == '~') {	/* =, ~ */
+
+		for (j = 0; j < nmaps; ++j) {
+		    if (!strcmp
+			(s_rules[rule_num].parse_queue[i - 1],
+			 s_maps[j].name)) {
+			for (k = 0; k < s_maps[j].nsets; ++k) {
+			    if (!strcmp
+				(s_rules[rule_num].parse_queue[i + 1],
+				 s_maps[j].sets[k].setname)) {
+
+				s_rules[rule_num].work_queue[work_queue_pos] =
+				    t_VAL;
+				s_rules[rule_num].value_queue[work_queue_pos].
+				    value = &s_maps[j].cell;
+				s_rules[rule_num].value_queue[work_queue_pos].
+				    set = &s_maps[j].sets[k];
+				s_rules[rule_num].value_queue[work_queue_pos].
+				    oper = *s_rules[rule_num].parse_queue[i];
+				done = 0;
+				break;
+			    }
+			}
+		    }
+		}		/* END for j */
+
+		if (done)
+		    G_fatal_error(_("There is no map <%s> or variable <%s>"),
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i + 1]);
+		/* end for j */
+
+		if (s_rules[rule_num].work_queue[work_queue_pos - 1] != t_AND
+		    && s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_OR &&
+		    s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_START &&
+		    s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_LBRC)
+		    G_fatal_error(_("line %d Syntax error near <%s %s>"),
+				  rule_num + 1,
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i]);
+
+		work_queue_pos++;
+		continue;
+	    }			/* END =, ~ */
+
+	    if (*s_rules[rule_num].parse_queue[i] == '&' || *s_rules[rule_num].parse_queue[i] == '|') {	/* operators &, | */
+
+		s_rules[rule_num].work_queue[work_queue_pos] =
+		    (*s_rules[rule_num].parse_queue[i] == '|') ? t_OR : t_AND;
+
+		if (s_rules[rule_num].work_queue[work_queue_pos - 1] != t_VAL
+		    && s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_RBRC)
+		    G_fatal_error(_("line %d Syntax error near <%s %s>"),
+				  rule_num + 1,
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i]);
+
+		work_queue_pos++;
+		continue;
+	    }			/* END &, | */
+
+	    if (*s_rules[rule_num].parse_queue[i] == '(') {
+
+		s_rules[rule_num].work_queue[work_queue_pos] = t_LBRC;
+		lbrc++;
+
+		if (s_rules[rule_num].work_queue[work_queue_pos - 1] != t_AND
+		    && s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_OR &&
+		    s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_START &&
+		    s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_LBRC)
+		    G_fatal_error(_("line %d Syntax error near <%s %s>"),
+				  rule_num + 1,
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i]);
+
+		work_queue_pos++;
+		continue;
+	    }			/* END ( */
+
+	    if (*s_rules[rule_num].parse_queue[i] == ')') {
+
+		s_rules[rule_num].work_queue[work_queue_pos] = t_RBRC;
+		rbrc++;
+
+		if (s_rules[rule_num].work_queue[work_queue_pos - 1] != t_VAL
+		    && s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_RBRC)
+		    G_fatal_error(_("line %d Syntax error near <%s %s>"),
+				  rule_num + 1,
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i]);
+
+		work_queue_pos++;
+		continue;
+	    }			/* END ) */
+
+	    if (*s_rules[rule_num].parse_queue[i] == '}') {
+
+		s_rules[rule_num].work_queue[work_queue_pos] = t_STOP;
+
+		if (s_rules[rule_num].work_queue[work_queue_pos - 1] != t_VAL
+		    && s_rules[rule_num].work_queue[work_queue_pos - 1] !=
+		    t_RBRC)
+		    G_fatal_error(_("line %d Syntax error near <%s %s>"),
+				  rule_num + 1,
+				  s_rules[rule_num].parse_queue[i - 1],
+				  s_rules[rule_num].parse_queue[i]);
+
+		work_queue_pos++;
+		continue;
+	    }			/* END } */
+
+	}			/* most external loop */
+
+	if (lbrc != rbrc)
+	    G_fatal_error(_("line %d Left and right of braces do not match"),
+			  rule_num + 1);
+
+    }				/* END check if rule syntax is proper and map names and vars values exist */
+
+    return 0;
+}				/* END parse_rules */

Added: grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/system.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/system.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.fuzzy/r.fuzzy.system/system.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,198 @@
+#include "local_proto.h"
+
+float implicate(void)
+{
+
+    int i, j;
+    //float *agregate = NULL;
+    int set_index;
+    float consequent;
+    float max_antecedent = 0;
+    float max_agregate = 0;
+    float result;
+
+    memset(agregate,0,resolution * sizeof(float));
+
+    for (j = 0; j < nrules; ++j) {
+	antecedents[j] = parse_expression(j);
+	max_antecedent =
+	    (max_antecedent >
+	     antecedents[j]) ? max_antecedent : antecedents[j]; 
+   }
+
+    if (max_antecedent == 0. && !coor_proc)
+	return -9999;		/* for all rules value is 0 */
+
+    for (j = 0; j < nrules; ++j) {
+
+	if (defuzzyfication > d_BISECTOR && antecedents[j] < max_antecedent && !coor_proc)
+	    continue;
+	    
+	    set_index = s_rules[j].output_set_index;
+
+	for (i = 0; i < resolution; ++i) {
+	    
+	    consequent = fuzzy(universe[i],
+			       &s_maps[output_index].sets[set_index]);
+	    
+	    consequent = (!implication) ? MIN(antecedents[j], consequent) :
+		antecedents[j] * consequent;
+	    agregate[i] = MAX(agregate[i], consequent);
+	    
+	   max_agregate = (max_agregate > agregate[i]) 
+				? max_agregate : agregate[i];
+	   
+
+	    if (coor_proc)
+		visual_output[i][j + 1] = consequent;
+	}
+	
+    }
+    if (coor_proc)
+	for (i = 0; i < resolution; ++i)
+	    visual_output[i][j + 1] = agregate[i];
+
+     result=defuzzify(defuzzyfication, max_agregate);
+     return result;
+}
+
+float parse_expression(int n)
+{
+
+    /*  tokens and actions must heve the same order */
+    actions parse_tab[t_size][t_size] = {
+	/* stk -----------INPUT------------------ */
+	/*  		{   &  | ~   =  (  )  }   */
+	/*      --  -- -- -- -- -- -- -- */
+	/* { */ {E, S, S, E, E, S, E, A},
+	/* & */ {E, R, R, E, E, S, R, R},
+	/* | */ {E, R, R, E, E, S, R, R},
+	/* ~ */ {E, E, E, E, E, E, E, E},
+	/* = */ {E, E, E, E, E, E, E, E},
+	/* ( */ {E, S, S, E, E, S, S, E},
+	/* ) */ {E, R, R, E, E, E, R, R},
+	/* } */ {E, E, E, E, E, E, E, E}
+    };
+
+    tokens operator_stack[STACKMAX];
+    float values_stack[STACKMAX];
+
+    int i = 0, k = 0;
+    int opr_top = 0;
+    int val_top = 0;
+    int set_index;
+    float f_value;
+
+
+    do {
+	if (s_rules[n].work_queue[i] == t_START) {	/* first token */
+	    if (i > 0)
+		G_fatal_error("operator stack error, contact author");
+	    operator_stack[opr_top] = t_START;
+	    continue;
+	}
+
+	if (s_rules[n].work_queue[i] == t_VAL) {
+	    f_value =
+		fuzzy(*s_rules[n].value_queue[i].value, s_rules[n].value_queue[i].set);
+	    values_stack[++val_top] =	(s_rules[n].value_queue[i].oper == '~') ? 
+				f_not(f_value, family) :	f_value;
+	    continue;
+	}
+
+	if (s_rules[n].work_queue[i] < t_size) {
+	    switch (parse_tab[operator_stack[opr_top]]
+		    [s_rules[n].work_queue[i]]) {
+
+	    case E:		/* error */
+		G_fatal_error("Stack error, contact author");
+		break;
+
+	    case S:		/* shift */
+		operator_stack[++opr_top] = s_rules[n].work_queue[i];
+		break;
+
+	    case R:		/* reduce */
+
+		switch (operator_stack[opr_top]) {
+
+		case t_AND:
+		    values_stack[val_top - 1] =
+			f_and(values_stack[val_top],
+			      values_stack[val_top - 1], family);
+		    val_top--;
+		    break;
+
+		case t_OR:
+		    values_stack[val_top - 1] =
+			f_or(values_stack[val_top], values_stack[val_top - 1],
+			     family);
+		    val_top--;
+		    break;
+
+		case t_RBRC:
+		    opr_top--;
+		    break;
+		}
+
+		opr_top--;
+		i--;
+		break;
+
+	    case A:		/* accept */
+	
+		if (!val_top)
+		    G_fatal_error("Stack error at end, contact autor");
+		return values_stack[val_top];
+	
+	    }
+	}
+
+    } while (s_rules[n].work_queue[i++] != t_STOP);
+    
+    G_fatal_error("Parse Stack empty, contact autor");
+}
+
+
+
+float defuzzify(int defuzzyfication, float max_agregate)
+{
+    int i;
+    float d_value = 0;
+    float sum_agregate = 0;
+    float tmp;
+
+    for (i = 0; i < resolution; sum_agregate += agregate[i++]) ;
+
+    switch (defuzzyfication) {
+
+    case d_CENTEROID:
+	for (i = 0; i < resolution; ++i)
+	    d_value += (universe[i] * agregate[i]);
+	return d_value / sum_agregate;
+
+    case d_BISECTOR:
+	for (i = 0, tmp = 0; (tmp += agregate[i]) < sum_agregate / 2; ++i) ;
+	return universe[i];
+
+    case d_MINOFHIGHEST:
+	for (i = 0; agregate[i] < max_agregate;++i) ;
+	return universe[i];
+
+    case d_MAXOFHIGHEST:
+	for (i = resolution; agregate[i] < max_agregate;--i) ;
+	return universe[i];
+
+    case d_MEANOFHIGHEST:
+	sum_agregate = 0;
+	for (i = 0; i < resolution; ++i) {
+	    if (agregate[i] < max_agregate)
+		continue;
+	    d_value += (universe[i] * agregate[i]);
+	    sum_agregate += agregate[i];
+	}
+	return d_value / sum_agregate;
+    }
+
+    return -9999;
+}

Added: grass-addons/grass7/grass7/raster/r.gdd/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.gdd/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.gdd/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.gdd
+
+LIBES = $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+EXTRA_LIBS = $(OMPLIB)
+EXTRA_CFLAGS = $(OMPCFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.gdd/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.gdd/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.gdd/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,379 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.gdd
+ * AUTHOR(S):    Markus Metz
+ *               based on r.series
+ * PURPOSE:      Calculate Growing Degree Days (GDDs)
+ * COPYRIGHT:    (C) 2012 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <math.h>
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+struct input
+{
+    const char *name;
+    int fd;
+    FCELL *buf;
+};
+
+struct output
+{
+    const char *name;
+    int fd;
+    FCELL *buf;
+};
+
+int main(int argc, char *argv[])
+{
+    struct GModule *module;
+    struct
+    {
+	struct Option *input, *gdd, *file, *output, *range,
+	              *scale, *shift, *baseline, *cutoff;
+    } parm;
+    struct
+    {
+	struct Flag *nulls, *lazy, *avg;
+    } flag;
+    int i;
+    int num_inputs, max_inputs, gdd_in;
+    struct input *inputs = NULL;
+    struct output *out = NULL;
+    struct History history;
+    struct Colors colors;
+    int nrows, ncols;
+    int row, col;
+    double lo, hi, tscale, tshift, baseline, cutoff;
+    FCELL fnull;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("series"));
+    module->description =
+	_("Makes each output cell value a "
+	  "function of the values assigned to the corresponding cells "
+	  "in the input raster map layers.");
+
+    parm.input = G_define_standard_option(G_OPT_R_INPUTS);
+    parm.input->required = NO;
+
+    parm.gdd = G_define_standard_option(G_OPT_R_INPUT);
+    parm.gdd->key = "gdd";
+    parm.gdd->description = _("Existing GDD map to be added to output");
+    parm.gdd->required = NO;
+
+    parm.file = G_define_standard_option(G_OPT_F_INPUT);
+    parm.file->key = "file";
+    parm.file->description = _("Input file with raster map names, one per line");
+    parm.file->required = NO;
+
+    parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
+    parm.output->multiple = NO;
+
+    parm.scale = G_define_option();
+    parm.scale->key = "scale";
+    parm.scale->type = TYPE_DOUBLE;
+    parm.scale->answer = "1.0";
+    parm.scale->required = NO;
+    parm.scale->description = _("Scale factor for input");
+
+    parm.shift = G_define_option();
+    parm.shift->key = "shift";
+    parm.shift->type = TYPE_DOUBLE;
+    parm.shift->answer = "0.0";
+    parm.shift->required = NO;
+    parm.shift->description = _("Shift factor for input");
+
+    parm.baseline = G_define_option();
+    parm.baseline->key = "baseline";
+    parm.baseline->type = TYPE_DOUBLE;
+    parm.baseline->required = NO;
+    parm.baseline->answer = "10";
+    parm.baseline->description = _("Baseline temperature");
+
+    parm.cutoff = G_define_option();
+    parm.cutoff->key = "cutoff";
+    parm.cutoff->type = TYPE_DOUBLE;
+    parm.cutoff->required = NO;
+    parm.cutoff->answer = "30";
+    parm.cutoff->description = _("Cutoff temperature");
+
+    parm.range = G_define_option();
+    parm.range->key = "range";
+    parm.range->type = TYPE_DOUBLE;
+    parm.range->key_desc = "lo,hi";
+    parm.range->description = _("Ignore values outside this range");
+
+    flag.avg = G_define_flag();
+    flag.avg->key = 'a';
+    flag.avg->description = _("Use average instead of min, max");
+
+    flag.nulls = G_define_flag();
+    flag.nulls->key = 'n';
+    flag.nulls->description = _("Propagate NULLs");
+
+    flag.lazy = G_define_flag();
+    flag.lazy->key = 'z';
+    flag.lazy->description = _("Don't keep files open");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    lo = -1.0 / 0.0;
+    hi = 1.0 / 0.0;
+    if (parm.range->answer) {
+	lo = atof(parm.range->answers[0]);
+	hi = atof(parm.range->answers[1]);
+    }
+
+    if (parm.scale->answer)
+	tscale = atof(parm.scale->answer);
+    else
+	tscale = 1.;
+
+    if (parm.shift->answer)
+	tshift = atof(parm.shift->answer);
+    else
+	tshift = 0.;
+
+    baseline = atof(parm.baseline->answer);
+    cutoff = atof(parm.cutoff->answer);
+    
+    if (cutoff <= baseline)
+        G_fatal_error(_("'%s' must be > '%s'"), parm.cutoff->key,
+	                                        parm.baseline->key);
+
+    if (parm.input->answer && parm.file->answer)
+        G_fatal_error(_("input= and file= are mutually exclusive"));
+ 
+    if (!parm.input->answer && !parm.file->answer)
+        G_fatal_error(_("Please specify input= or file="));
+
+    max_inputs = 0;
+    /* process the input maps from the file */
+    if (parm.file->answer) {
+	FILE *in;
+    
+	in = fopen(parm.file->answer, "r");
+	if (!in)
+	    G_fatal_error(_("Unable to open input file <%s>"), parm.file->answer);
+    
+	num_inputs = 0;
+
+	for (;;) {
+	    char buf[GNAME_MAX];
+	    char *name;
+	    struct input *p;
+
+	    if (!G_getl2(buf, sizeof(buf), in))
+		break;
+
+	    name = G_chop(buf);
+
+	    /* Ignore empty lines */
+	    if (!*name)
+		continue;
+
+	    if (num_inputs >= max_inputs) {
+		max_inputs += 100;
+		inputs = G_realloc(inputs, max_inputs * sizeof(struct input));
+	    }
+	    p = &inputs[num_inputs++];
+
+	    p->name = G_store(name);
+	    G_verbose_message(_("Reading raster map <%s>..."), p->name);
+	    p->buf = Rast_allocate_f_buf();
+	    if (!flag.lazy->answer)
+		p->fd = Rast_open_old(p->name, "");
+	}
+
+	if (num_inputs < 1)
+	    G_fatal_error(_("No raster map name found in input file"));
+
+	fclose(in);
+    }
+    else {
+    	for (i = 0; parm.input->answers[i]; i++)
+	    ;
+    	num_inputs = i;
+
+    	if (num_inputs < 1)
+	    G_fatal_error(_("Raster map not found"));
+
+    	inputs = G_malloc(num_inputs * sizeof(struct input));
+
+    	for (i = 0; i < num_inputs; i++) {
+	    struct input *p = &inputs[i];
+
+	    p->name = parm.input->answers[i];
+	    G_verbose_message(_("Reading raster map <%s>..."), p->name);
+	    p->buf = Rast_allocate_f_buf();
+	    if (!flag.lazy->answer)
+		p->fd = Rast_open_old(p->name, "");
+    	}
+	max_inputs = num_inputs;
+    }
+
+    if (parm.gdd->answer) {
+	struct input *p;
+
+	gdd_in = 1;
+	if (num_inputs + 1 >= max_inputs) {
+	    max_inputs += 2;
+	    inputs = G_realloc(inputs, max_inputs * sizeof(struct input));
+	}
+	p = &inputs[num_inputs];
+	p->name = parm.gdd->answer;
+	G_verbose_message(_("Reading raster map <%s>..."), p->name);
+	p->buf = Rast_allocate_f_buf();
+	if (!flag.lazy->answer)
+	    p->fd = Rast_open_old(p->name, "");
+    }
+    else
+	gdd_in = 0;
+
+    out = G_calloc(1, sizeof(struct output));
+
+    out->name = parm.output->answer;
+
+    out->buf = Rast_allocate_f_buf();
+    out->fd = Rast_open_new(out->name, FCELL_TYPE);
+
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    
+    Rast_set_f_null_value(&fnull, 1);
+
+    /* process the data */
+    G_verbose_message(_("Percent complete..."));
+
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 2);
+
+	if (flag.lazy->answer) {
+	    /* Open the files only on run time */
+	    for (i = 0; i < num_inputs + gdd_in; i++) {
+		inputs[i].fd = Rast_open_old(inputs[i].name, "");
+		Rast_get_f_row(inputs[i].fd, inputs[i].buf, row);
+		Rast_close(inputs[i].fd);
+	    }
+	}
+	else {
+	    for (i = 0; i < num_inputs + gdd_in; i++)
+	        Rast_get_f_row(inputs[i].fd, inputs[i].buf, row);
+	}
+
+        #pragma omp for schedule (static) private (col)
+
+	for (col = 0; col < ncols; col++) {
+	    int null = 0, non_null = 0;
+	    FCELL min, max, avg, gdd;
+
+	    min = fnull;
+	    max = fnull;
+	    avg = 0;
+
+	    for (i = 0; i < num_inputs; i++) {
+		FCELL v = inputs[i].buf[col];
+
+		if (Rast_is_f_null_value(&v))
+		    null = 1;
+		else {
+		    v = v * tscale + tshift;
+		    if (parm.range->answer && (v < lo || v > hi)) {
+			null = 1;
+		    }
+		    else {
+			if (flag.avg->answer)
+			    avg += v;
+			else {
+			    if (Rast_is_f_null_value(&min) || min > v)
+				min = v;
+			    if (Rast_is_f_null_value(&max) || max < v)
+				max = v;
+			}
+			non_null++;
+		    }
+		}
+	    }
+
+	    if (!non_null || (null && flag.nulls->answer)) {
+		if (gdd_in)
+		    gdd = inputs[num_inputs].buf[col];
+		else
+		    gdd = fnull;
+	    }
+	    else {
+
+		if (flag.avg->answer) {
+		    avg /= non_null;
+
+		    if (avg < baseline)
+			avg = baseline;
+		    if (avg > cutoff)
+			avg = cutoff;
+
+		    gdd = avg - baseline;
+		}
+		else {
+		    if (min < baseline)
+			min = baseline;
+		    if (min > cutoff)
+			min = cutoff;
+		    if (max < baseline)
+			max = baseline;
+		    if (max > cutoff)
+			max = cutoff;
+
+		    gdd = (min + max) / 2. - baseline;
+		}
+
+		if (gdd < 0.)
+		    gdd = 0.;
+		if (gdd_in)
+		    gdd += inputs[num_inputs].buf[col];
+
+	    }
+	    out->buf[col] = gdd;
+	}
+
+	Rast_put_f_row(out->fd, out->buf);
+    }
+
+    G_percent(row, nrows, 2);
+
+    /* close output map */
+    Rast_close(out->fd);
+
+    Rast_short_history(out->name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(out->name, &history);
+
+    /* Close input maps */
+    if (!flag.lazy->answer) {
+    	for (i = 0; i < num_inputs + gdd_in; i++)
+	    Rast_close(inputs[i].fd);
+    }
+
+    /* set gdd color table */
+    Rast_init_colors(&colors);
+    Rast_make_colors(&colors, "gdd", 0, 6000);
+    Rast_write_colors(out->name, G_mapset(), &colors);
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.gdd/r.gdd.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.gdd/r.gdd.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.gdd/r.gdd.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,106 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.gdd</em> calculates (accumulated) growing degree days (GDDs) and 
+Winkler indices from several input maps with temperature data for 
+different times of the day.
+<p>
+The formula for calculating GDDs is
+<div class="code"><pre>
+    gdd = (max + min) / 2 - baseline
+</pre></div>
+The formula for calculating the Winkler index is
+<div class="code"><pre>
+    gdd = average - baseline
+</pre></div>
+with <em>min</em> being the minimum daily temperature, <em>max</em> 
+the maximum daily temperature and <em>average</em> the average daily 
+temperature. The <em>min</em>, <em>max</em> and <em>average</em> values 
+are automatically calculated from the input temperature maps.
+<p>
+The <em>shift</em> and <em>scale</em> values are applied directly to the 
+input values. The <em>baseline</em>, <em>cutoff</em>, and <em>range</em> 
+options are applied to the shifted and scaled values.
+<p>
+Any <em>min</em>, <em>max</em> and <em>average</em> temperature values 
+above the <em>cutoff</em> value are set to <em>cutoff</em>, and any 
+<em>min</em>, <em>max</em> and <em>average</em> values below the 
+<em>baseline</em> value are set to <em>baseline</em>. Negative results 
+are set to 0 (zero). 
+<p>
+If an existing map is provided with the <em>gdd</em> option, the 
+values of this map are added to the output, thus accumulating GDDs.
+
+<h2>NOTES</h2>
+
+The <em>scale</em> and <em>shift</em> parameters are used to transform 
+input values with
+<div class="code"><pre>
+    new = old * scale + shift
+</pre></div>
+<p>
+With the <em>-n</em> flag, any cell for which any of the 
+corresponding input cells are NULL is automatically set to NULL 
+(NULL propagation) and the GDD value is not calculated.
+<p>
+Without the <em>-n</em> flag, all non-NULL cells are used to 
+calculate the current GDD.
+<p>
+If the <em>range=</em> option is given, any values which fall outside 
+that range will be treated as if they were NULL. Note that the range is 
+applied to the scaled and shifted input data. The <em>range</em> 
+parameter can be set to <em>low,high</em> thresholds: 
+values outside of this range are treated as NULL (i.e., they will be 
+ignored by most aggregates, or will cause the result to be NULL if -n 
+is given). The <em>low,high</em> thresholds are floating point, so use 
+<em>-inf</em> or <em>inf</em> for a single threshold (e.g., 
+<em>range=0,inf</em> to ignore negative values, or 
+<em>range=-inf,-200.4</em> to ignore values above -200.4).
+<p>
+The number of raster maps to be processed is given by the limit of the 
+operating system. For example, both the hard and soft limits are 
+typically 1024. The soft limit can be changed with e.g. 
+<tt>ulimit -n 1500</tt> (UNIX-based operating systems) but not higher 
+than the hard limit. If it is too low, you can as superuser add an 
+entry in
+
+<div class="code"><pre>
+/etc/security/limits.conf
+# <domain>      <type>  <item>         <value>
+your_username  hard    nofile          1500
+</pre></div>
+
+This would raise the hard limit to 1500 file. Be warned that more
+files open need more RAM.
+
+<p>
+Use the <em>file</em> option to analyze large amount of raster maps 
+without hitting open files limit and the size limit of command line 
+arguments. The computation is slower than the <em>input</em> option 
+method. For every sinlge row in the output map(s) all input maps are 
+opened and closed. The amount of RAM will rise linear with the 
+number of specified input maps. The input and file options are 
+mutually exclusive. Input is a text file with a new line separated 
+list of raster map names and optional weights. As separator between 
+the map name and the weight the charachter | must be used.
+
+<h2>EXAMPLES</h2>
+
+Example with MODIS Land Surface Temperature, transforming values from 
+Kelvin * 50 to degrees Celsius:
+<div class="code"><pre>
+r.gdd in=MOD11A1.Day,MOD11A1.Night,MYD11A1.Day,MYD11A1.Night out=MCD11A1.GDD \
+      scale=0.02 shift=-273.15 baseline=10 cutoff=30
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em><a href="r.series.html">r.series</a>,
+<a href="g.mlist.html">g.mlist</a>,
+<a href="g.region.html">g.region</a>
+</em>
+
+<h2>AUTHOR</h2>
+
+Markus Metz (based on r.series)
+
+<p><i>Last changed: $Date: 2012-07-03 23:47:59 +0200 (Tue, 03 Jul 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.houghtransform/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,20 @@
+# fix this relative to include/
+# or use absolute path to the GRASS source code
+MODULE_TOPDIR = ../..
+
+PGM = r.houghtransform
+
+LIBES = $(VECTORLIB) $(GISLIB) $(RASTERLIB)  $(GMATHLIB)
+DEPENDENCIES = $(VECTORDEP) $(GISDEP) $(RASTERDEP) 
+
+EXTRA_INC = $(VECT_INC)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+EXTRA_CFLAGS = $(VECT_CFLAGS) -Wno-sign-compare -Wall -Wextra -O0 -Wconversion
+
+LINK = $(CXX)
+
+#ifneq ($(strip $(CXX)),)
+default: cmd
+#endif

Added: grass-addons/grass7/grass7/raster/r.houghtransform/hough.cpp
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/hough.cpp	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/hough.cpp	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,267 @@
+#include "houghtransform.h"
+
+#include"linesegmentsextractor.h"
+#include "matrix.h"
+
+extern "C" {
+namespace grass {
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+#include <grass/gmath.h>
+}
+}
+
+using grass::DCELL;
+using grass::CELL;
+using grass::G__calloc;
+using grass::Cell_head;
+using grass::Map_info;
+
+using grass::Vect_new_cats_struct;
+using grass::Vect_new_line_struct;
+
+using grass::Rast_allocate_c_input_buf;
+using grass::Rast_open_old;
+using grass::Rast_get_row;
+using grass::Rast_close;
+
+using grass::Rast_window_rows;
+using grass::Rast_window_cols;
+using grass::Rast_allocate_c_buf;
+using grass::Rast_open_fp_new;
+using grass::Rast_put_c_row;
+using grass::Rast_get_cellhd;
+
+using grass::G_gettext;
+using grass::G_fatal_error;
+using grass::G_debug;
+using grass::G_free;
+
+using grass::Colors;
+using grass::Range;
+using grass::G_mapset;
+
+/** Loads map into memory.
+
+  \param[out] mat map in a matrix (row order), field have to be allocated
+  */
+template <typename Matrix>
+void read_raster_map(const char *name, const char *mapset, int nrows,
+                            int ncols, Matrix& mat)
+{
+
+    int r, c;
+
+    int map_fd;
+
+    CELL *row_buffer;
+
+    CELL cell_value;
+
+    row_buffer = Rast_allocate_c_buf();
+
+    /* load map */
+    map_fd = Rast_open_old(name, mapset);
+    if (map_fd < 0) {
+        G_fatal_error(_("Error opening first raster map <%s>"), name);
+    }
+
+    G_debug(1, "fd %d %s %s", map_fd, name, mapset);
+
+    //    if ((first_map_R_type =
+    //         Rast_map_type(templName, mapset)) < 0)
+    //        G_fatal_error(_("Error getting first raster map type"));
+
+    for (r = 0; r < nrows; r++) {
+        Rast_get_row(map_fd, row_buffer, r, CELL_TYPE);
+
+        for (c = 0; c < ncols; c++) {
+            cell_value = row_buffer[c];
+            if (!Rast_is_c_null_value(&cell_value))
+                mat(r, c) = cell_value;
+            else
+                mat(r, c) = 0.0;
+        }
+    }
+    G_free(row_buffer);
+
+    Rast_close(map_fd);
+}
+
+void apply_hough_colors_to_map(const char *name)
+{
+    struct Colors colors;
+    struct Range range;
+    CELL min, max;
+
+    Rast_read_range(name, G_mapset(), &range);
+    Rast_get_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_write_colors(name, G_mapset(), &colors);
+}
+
+template <typename Matrix>
+void create_raster_map(const char *name, struct Cell_head *window, const Matrix& mat)
+{
+    struct Cell_head original_window;
+    CELL *cell_real;
+    int rows, cols; /* number of rows and columns */
+    long totsize; /* total number of data points */ // FIXME: make clear the size_t usage
+    int mapfd;
+
+    /* get the rows and columns in the current window */
+    rows = mat.rows();
+    cols = mat.columns();
+    totsize = rows * cols;
+
+    G_get_set_window(&original_window);
+
+    window->bottom = 0;
+    window->top = rows;
+    window->cols = cols;
+    window->east = cols;
+    window->north = rows;
+    window->ns_res = 1;
+    window->rows = rows;
+    window->south = 0;
+    window->west = 0;
+    window->ew_res = 1;
+    window->tb_res = 1;
+
+    Rast_set_window(window);
+
+    /* allocate the space for one row of cell map data */
+    cell_real = Rast_allocate_c_buf();
+
+    /* open the output cell maps */
+    mapfd = Rast_open_fp_new(name);
+
+    for (int i = 0; i < rows; i++) {
+        for (int j = 0; j < cols; j++) {
+            cell_real[j] = mat(i, j);
+        }
+        Rast_put_c_row(mapfd, cell_real);
+    }
+
+    Rast_close(mapfd);
+    G_free(cell_real);
+
+    Rast_set_window(&original_window);
+}
+
+/**
+  \param cellhd raster map header, used for converting rows/cols to easting/northing
+  */
+void create_vector_map(const char * name, const SegmentList& segments,
+                       const Cell_head* cellhd)
+{
+    struct Map_info Map;
+    Vect_open_new(&Map, name, 0);
+
+    struct grass::line_cats *Cats;
+    struct grass::line_pnts *points;
+    Cats = Vect_new_cats_struct();
+    points = Vect_new_line_struct();
+
+
+    for (size_t i = 0; i < segments.size(); ++i)
+    {
+        const Segment& seg = segments[i];
+
+        double y1 = Rast_row_to_northing(seg.first.first, cellhd);
+        double x1 = Rast_col_to_easting(seg.first.second, cellhd);
+        double y2 = Rast_row_to_northing(seg.second.first, cellhd);
+        double x2 = Rast_col_to_easting(seg.second.second, cellhd);
+
+        Vect_reset_cats(Cats);
+        Vect_cat_set(Cats, 1, i+1); // cat is segment number (counting from one)
+
+        Vect_reset_line(points);
+        Vect_append_point(points, x1, y1, 0);
+        Vect_append_point(points, x2, y2, 0);
+
+        Vect_write_line(&Map, GV_LINE, points, Cats);
+    }
+
+    Vect_destroy_cats_struct(Cats);
+    Vect_destroy_line_struct(points);
+    
+    Vect_build(&Map);
+    Vect_close(&Map);
+}
+
+template <typename Matrix>
+void extract_line_segments(const Matrix &I,
+                           const HoughTransform::Peaks& peaks,
+                           const HoughTransform::TracebackMap& houghMap,
+                           ExtractParametres extractParametres,
+                           SegmentList& segments)
+{
+    for (size_t i = 0; i < peaks.size(); ++i)
+    {
+        const HoughTransform::Peak& peak = peaks[i];
+
+        double theta = peak.coordinates.second;
+
+        HoughTransform::TracebackMap::const_iterator coordsIt =
+                houghMap.find(peak.coordinates);
+        if (coordsIt != houghMap.end())
+        {
+            const HoughTransform::CoordinatesList& lineCoordinates = coordsIt->second;
+
+            LineSegmentsExtractor extractor(I, extractParametres);
+
+            extractor.extract(lineCoordinates, (theta-90)/180*M_PI, segments);
+        }
+        else
+        {
+            // logic error
+        }
+    }
+}
+
+void hough_peaks(HoughParametres houghParametres,
+                 ExtractParametres extractParametres,
+                 const char *name, const char *mapset, size_t nrows, size_t ncols,
+                 const char *anglesMapName,
+                 const char *houghImageName, const char *result)
+{
+    typedef matrix::Matrix<DCELL> Matrix;
+    Matrix I(nrows, ncols);
+    read_raster_map(name, mapset, nrows, ncols, I);
+
+    HoughTransform hough(I, houghParametres);
+
+    if (anglesMapName != NULL)
+    {
+        Matrix angles(nrows, ncols);
+        read_raster_map(anglesMapName, mapset, nrows, ncols, angles);
+        hough.compute(angles);
+    }
+    else
+    {
+        hough.compute();
+    }
+
+    hough.findPeaks();
+
+    if (houghImageName != NULL)
+    {
+        struct Cell_head window;
+        Rast_get_cellhd(name, "", &window);
+        create_raster_map(houghImageName, &window, hough.getHoughMatrix());
+        apply_hough_colors_to_map(houghImageName);
+    }
+
+    const HoughTransform::Peaks& peaks = hough.getPeaks();
+    const HoughTransform::TracebackMap& houghMap = hough.getHoughMap();
+    SegmentList segments;
+
+    extract_line_segments(I, peaks, houghMap, extractParametres, segments);
+
+    Cell_head cellhd;
+    Rast_get_window(&cellhd);
+    create_vector_map(result, segments, &cellhd);
+}

Added: grass-addons/grass7/grass7/raster/r.houghtransform/hough.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/hough.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/hough.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,13 @@
+#ifndef HOUGH_H
+#define HOUGH_H
+
+#include "houghparameters.h"
+
+extern "C" {
+#include <grass/gis.h>
+#include <grass/raster.h>
+}
+
+void hough_peaks(HoughParametres houghParametres, ExtractParametres extractParametres, const char *name, const char *mapset, size_t nrows, size_t ncols, const char *angleMapName, const char *houghImageName, const char *result);
+
+#endif // HOUGH_H

Added: grass-addons/grass7/grass7/raster/r.houghtransform/houghparameters.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/houghparameters.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/houghparameters.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,21 @@
+#ifndef HOUGHPARAMETERS_H
+#define HOUGHPARAMETERS_H
+
+struct HoughParametres
+{
+    double angleWidth;
+    int maxPeaksNum;
+    int threshold;
+    int sizeOfNeighbourhood;
+};
+
+struct ExtractParametres
+{
+    int gapSize;
+    int maxNumOfGaps;
+    int maxGap;
+    int lineLength;
+    int lineWidth;
+};
+
+#endif // HOUGHPARAMETERS_H

Added: grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.cpp
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.cpp	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.cpp	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,243 @@
+#include "houghtransform.h"
+
+/* helpers */
+
+struct SortByX
+{
+    bool operator()(const HoughTransform::Coordinates& c1, const HoughTransform::Coordinates& c2) const
+    {
+
+        return c1.first < c2.first;
+    }
+};
+
+struct SortByY
+{
+    bool operator()(const HoughTransform::Coordinates& c1, const HoughTransform::Coordinates& c2) const
+    {
+
+        return c1.second < c2.second;
+    }
+};
+
+
+/* ctors */
+
+HoughTransform::HoughTransform(const Matrix &matrix, const HoughParametres& parametrs)
+    : mOriginalMatrix(matrix), mParams(parametrs)
+{
+    mNumR = mOriginalMatrix.rows();
+    mNumC = mOriginalMatrix.columns();
+
+    mThetas = ColumnVector(Range(-M_PI/2.0, M_PI/2.0, M_PI/180.0).matrix_value ());
+
+    const float diag_length = std::sqrt(mNumR*mNumR + mNumC*mNumC);
+    mNumBins = ceil(diag_length) - 1;
+
+    mHoughMatrix = Matrix(mNumBins, mThetas.length(), 0.0);
+
+    c_2 = ceil(mNumC/2.);
+    r_2 = ceil(mNumR/2.);
+
+    first_bins = 1 - ceil(mNumBins/2.0);
+}
+
+/* functions */
+
+void HoughTransform::compute()
+{
+    for (int x = 0; x < mNumR; x++)
+    {
+        for (int y = 0; y < mNumC; y++)
+        {
+            if (mOriginalMatrix(x, y) == 1)
+            {
+                computeHoughForXY(x, y, 0, mThetas.length());
+            }
+        }
+    }
+
+}
+
+void HoughTransform::computeHoughForXY(int x, int y, size_t minIndex, size_t maxIndex)
+{
+    for (size_t i = minIndex; i < maxIndex; i++)
+    {
+        const double theta = mThetas(i);
+        const double rho_d = std::cos(theta)*(x - c_2) + std::sin(theta)*(y - r_2);
+        const int rho = floor(rho_d + 0.5);
+        const int bin = rho - first_bins;
+
+        if ((bin > 0) && (bin < mNumBins))
+        {
+            mHoughMatrix(bin, i)++;
+            mHoughMap[Coordinates(bin, i)].push_back(Coordinates(x, y));
+            mOriginalMap[Coordinates(x, y)].push_back(Coordinates(bin, i));
+        }
+    }
+}
+
+/**
+  Expecting angles to be in degrees in range [0,180).
+
+  Size of agles matrix must be the same as size of input edge matrix.
+  mNumR != angles.rows() && mNumC != angles.columns()
+  */
+void HoughTransform::compute(const Matrix& angles, double angleWith)
+{
+    for (int x = 0; x < mNumR; x++)
+    {
+        for (int y = 0; y < mNumC; y++)
+        {
+            if (mOriginalMatrix(x, y) == 1)
+            {
+                // gradient in mathematical axes
+                double angle = angles(x, y);
+                
+                // unify gradients
+                if (angle < 0)
+                    angle += 180;
+
+                // converting angle [0,180) to index
+                // in internal table of angles
+                // assuming that table size is 180
+                // TODO: angleIndex = mThetas.length() * angle/180
+                int angleIndex = angle;
+                int angleShift = angleWith/2 + 0.5;
+
+                 // FIXME: magic number
+                int minIndex = angleIndex - angleShift;
+                int maxIndex = angleIndex + angleShift;
+
+                if (minIndex < 0) {
+                    computeHoughForXY(x, y, 0, maxIndex);
+                    minIndex = 180 + minIndex;
+                    computeHoughForXY(x, y, minIndex, 180);
+                }
+                else if (maxIndex > 180)
+                {
+                    computeHoughForXY(x, y, minIndex, 180);
+                    maxIndex = maxIndex - 180;
+                    computeHoughForXY(x, y, 0, maxIndex);
+                }
+                else
+                {
+                    computeHoughForXY(x, y, minIndex, maxIndex);
+                }
+            }
+        }
+    }
+}
+
+void HoughTransform::findPeaks(int maxPeakNumber, int threshold, int sizeOfNeighbourhood)
+{
+    int maxIt = mHoughMatrix.rows() * mHoughMatrix.columns();
+    int peaksFound = 0;
+    for (int i = 0; i < maxIt; i++)
+    {
+        Coordinates coordinates;
+        int maxValue = findMax(mHoughMatrix, coordinates);
+
+        if (maxValue < threshold || peaksFound == maxPeakNumber )
+            break;
+
+        CoordinatesList neighbours(neighbourhood(coordinates, sizeOfNeighbourhood));
+
+        Coordinates beginLine, endLine;
+
+        removePeakEffect(neighbours, beginLine, endLine);
+
+        Peak peak(coordinates, maxValue, beginLine, endLine);
+        mPeaks.push_back(peak);
+        peaksFound++;
+    }
+}
+
+HoughTransform::CoordinatesList HoughTransform::neighbourhood(Coordinates &coordinates, const int sizeOfNeighbourhood)
+{
+    CoordinatesList list;
+    const int x = coordinates.first;
+    const int y = coordinates.second;
+    for (int i = -sizeOfNeighbourhood; i <= sizeOfNeighbourhood; i++)
+    {
+        for (int j = -sizeOfNeighbourhood; j <= sizeOfNeighbourhood; j++)
+        {
+            list.push_back(Coordinates(x + i, y + j));
+        }
+    }
+    return list;
+}
+
+void HoughTransform::removePeakEffect(const CoordinatesList &neighbours, Coordinates &beginLine, Coordinates &endLine)
+{
+    CoordinatesList lineList;
+    for (CoordinatesList::const_iterator it = neighbours.begin(), end = neighbours.end(); it != end; ++it)
+    {
+        CoordinatesList &toRemove = mHoughMap[*it];
+
+        for (CoordinatesList::const_iterator it1 = toRemove.begin(), end = toRemove.end(); it1 != end; ++it1)
+        {
+            if ( mOriginalMap.find(*it1) != mOriginalMap.end() )
+            {
+                CoordinatesList &toDecrease = mOriginalMap[*it1];
+
+                for (CoordinatesList::const_iterator it2 = toDecrease.begin(), end = toDecrease.end(); it2 != end; ++it2)
+                {
+                    mHoughMatrix(it2->first, it2->second)--;
+                }
+                mOriginalMap.erase(*it1);
+
+               lineList.push_back(*it1);
+            }
+        }
+    }
+    int angle = neighbours.front().second;
+    // what to do if find endpoints finds nothing reasonable?
+    findEndPoints(lineList, beginLine, endLine, angle);
+}
+
+/** \param list[in, out] will be sorted by y cooridinate
+  if angle is in range (45, 135] or by x otherwise
+  */
+bool HoughTransform::findEndPoints(CoordinatesList& list, Coordinates &beginLine, Coordinates &endLine, const value_type angle)
+{
+    if (angle > 45 && angle <= 135)
+    {
+        std::sort(list.begin(), list.end(), SortByY());
+    }
+    else
+    {
+        std::sort(list.begin(), list.end(), SortByX());
+    }
+
+    beginLine = list.front();
+    endLine = list.back();
+
+    return true;
+}
+
+int HoughTransform::findMax(const Matrix& matrix, Coordinates &coordinates)
+{
+    size_t rowIndex = 0;
+    size_t colIndex;
+    std::vector<size_t> colIndexes;
+
+    std::vector<value_type> rowMax = matrix.row_max(colIndexes);
+
+    int max = 0;
+    for (size_t i = 0; i < rowMax.size(); i++)
+    {
+        int tmp = rowMax[i];
+        if (tmp > max)
+        {
+            max = tmp;
+            rowIndex = i;
+        }
+    }
+    colIndex = colIndexes[rowIndex];
+
+    coordinates.first = rowIndex;
+    coordinates.second = colIndex;
+
+    return max;
+}

Added: grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/houghtransform.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,123 @@
+#ifndef HOUGHTRANSFORM_H
+#define HOUGHTRANSFORM_H
+
+#include "houghparameters.h"
+#include "matrix.h"
+
+#include <cmath>
+#include <vector>
+#include <list>
+#include <set>
+#include <map>
+#include <limits>
+#include <algorithm>
+
+#include <stdio.h>
+
+class HoughTransform
+{
+public:
+    /* types */
+    typedef double value_type;
+    typedef matrix::Matrix<value_type> Matrix;
+    typedef matrix::ColumnVector<double> ColumnVector;
+    typedef matrix::Range<double> Range;
+
+    /** This is class to provide compatible syntax with \c std::list. */
+    template <typename T>
+    class Vector: public std::vector<T>
+    {
+    public:
+
+        /**
+          Maybe it would be better to replace by an overload of sort function for list.
+          And use this function for list.
+          */
+        template <typename Comp>
+        void sort(Comp comp)
+        {
+            std::sort(this->begin(), this->end(), comp);
+        }
+        /** only for convenience, with some compiler optimalisation overhead shouldn't be so high  */
+        operator std::list<T>() const
+        {
+            std::list<T> tmp;
+            tmp.insert(tmp.begin(), this->begin(), this->end());
+            return tmp;
+        }
+    };
+
+    typedef std::pair<int, int> Coordinates;
+    typedef Vector<Coordinates> CoordinatesList;
+    typedef std::map<Coordinates, CoordinatesList> TracebackMap;
+
+    struct Peak
+    {
+        Peak(Coordinates coordinates, value_type value, Coordinates begin, Coordinates end)
+            : coordinates(coordinates), value(value), beginLine(begin), endLine(end)
+        {}
+        Coordinates coordinates;
+        int value;
+        Coordinates beginLine;
+        Coordinates endLine;
+    };
+
+    typedef std::vector<Peak> Peaks;
+
+    /* functions */
+
+    HoughTransform(const Matrix &matrix, const HoughParametres &parametrs);
+
+    void compute();
+    void compute(const Matrix& angles)
+    {
+        compute(angles, mParams.angleWidth);
+    }
+    void compute(const Matrix& angles, double angleWith);
+    void findPeaks()
+    {
+        findPeaks(mParams.maxPeaksNum, mParams.threshold, mParams.sizeOfNeighbourhood);
+    }
+    void findPeaks(int maxPeakNumber, int threshold,
+                   const int sizeOfNeighbourhood);
+
+    /* getters */
+
+    const Matrix & getHoughMatrix() const { return mHoughMatrix; }
+    const Matrix & getOrigMatrix()  const { return mOriginalMatrix; }
+    const Peaks & getPeaks() const { return mPeaks; }
+    const TracebackMap & getHoughMap() const { return mHoughMap; }
+
+private:
+
+    /* functions */
+
+    // some of these functions can be changed to non-member
+    CoordinatesList neighbourhood(Coordinates &coordinates, const int sizeOfNeighbourhood);
+    void removePeakEffect(const CoordinatesList &neighbours, Coordinates &beginLine, Coordinates &endLine);
+    bool findEndPoints(CoordinatesList& list, Coordinates &beginLine, Coordinates &endLine, const value_type angle);
+    int findMax(const Matrix& matrix, Coordinates &coordinates);
+    void computeHoughForXY(int x, int y, size_t minIndex, size_t maxIndex);
+
+    /* data members */
+
+    const Matrix& mOriginalMatrix;
+    Matrix mHoughMatrix;
+    TracebackMap mOriginalMap;
+    TracebackMap mHoughMap;
+    Peaks mPeaks;
+
+    HoughParametres mParams;
+
+    /* helper variables for computations */
+    int mNumR;
+    int mNumC;
+    ColumnVector mThetas;
+    int mNumBins;
+    int c_2;
+    int r_2;
+    int first_bins;
+};
+
+
+#endif // HOUGHTRANSFORM_H

Added: grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.cpp
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.cpp	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.cpp	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,261 @@
+#include "linesegmentsextractor.h"
+
+#include "matrix.h"
+
+#include <stdio.h>
+
+#include <cmath>
+#include <vector>
+#include <list>
+
+using namespace matrix;
+
+struct Point
+{
+    int x;
+    int y;
+};
+
+/* non-member functions */
+
+double segmentLenght(const Segment& segment)
+{
+    double x = segment.first.first - segment.second.first;
+    double y = segment.first.second - segment.second.second;
+    return std::sqrt(x*x + y*y);
+}
+
+bool checkBounds(int y, int x, int cols, int rows)
+{
+    if ( y < 0 || y >= cols || x < 0 || x >= rows )
+        return false;
+    return true;
+}
+
+template<typename Matrix>
+bool isData(const Matrix &I, const std::vector<int> &y, const std::vector<int> &x, const int cols, const int rows)
+{
+    for (size_t k = 0; k < y.size(); k++)
+    {
+        if (checkBounds(y.at(k), x.at(k), cols, rows) && I(x.at(k), y.at(k)))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void remove_points(LineCoordinates& lineCoordinates, const std::vector<int>& indicesI, const std::vector<int>& indicesJ)
+{
+    for (size_t i = 0; i < indicesI.size(); ++i)
+    {
+        std::pair<int, int> coords;
+        coords.second = indicesI[i];
+        coords.first = indicesJ[i];
+        lineCoordinates.remove(coords);
+    }
+}
+
+void find_indices(std::vector<int>& indicesI, std::vector<int>& indicesJ,
+                  const int shift, const bool xflag, const int x, const int y,
+                  const int line_width)
+{
+    if (xflag)
+    {
+        int tmp1, tmp2;
+        indicesJ[0] = x;
+        tmp1 = y >> shift;
+        tmp2 = tmp1;
+        indicesI[0] = tmp1;
+        for (int l = 1; l < line_width; l += 2)
+        {
+            indicesJ[l] = x;
+            indicesJ[l + 1] = x;
+            indicesI[l] = --tmp1;
+            indicesI[l + 1] = ++tmp2;
+        }
+    }
+    else
+    {
+        int tmp1, tmp2;
+        indicesI[0] = y;
+        tmp1 = x >> shift;
+        tmp2 = tmp1;
+        indicesJ[0] = tmp1;
+        for (int l = 1; l < line_width; l += 2)
+        {
+            indicesI[l] = y;
+            indicesI[l + 1] = y;
+            indicesJ[l] = --tmp1;
+            indicesJ[l + 1] = ++tmp2;
+        }
+    }
+}
+
+bool segmentContainsPoint(const Segment& segment, const std::pair<int, int>& p, bool xFlag, int tol)
+{
+  int min, max;
+  if (xFlag)
+  {
+    min = segment.first.first;
+    max = segment.second.first;
+    if (segment.first.first > segment.second.first)
+    {
+      min = segment.second.first;
+      max = segment.first.first;
+    }
+
+    if (p.first > min + tol && p.first <= max - tol)
+      return true;
+  }
+  else
+  {
+    min = segment.first.second;
+    max = segment.second.second;
+    if (segment.first.second > segment.second.second)
+    {
+      min = segment.second.second;
+      max = segment.first.second;
+    }
+    if (p.second > min + tol && p.second <= max - tol)
+      return true;
+  }
+  return false;
+}
+
+/* member functions */
+
+void LineSegmentsExtractor::extract(LineCoordinates lineCoordinates,
+                                    const double orient,
+                                    SegmentList& segments)
+{
+    const int rows = mImage.rows();
+    const int cols = mImage.columns();
+
+    float rho = 1.0;
+    float irho = 1./rho;
+
+    bool xflag;
+
+    std::vector<Point> line_end(2);
+    SegmentList newSegments;
+
+    // from the current point walk in each direction
+    // along the found line and extract the line segment
+    float a = -(float)(sin(orient) * irho); //-trigtab[theta_n*2+1];
+    float b = (float)(cos(orient) * irho); //trigtab[theta_n*2];
+
+    int dx0, dy0;
+    const int shift = 16;
+
+    std::vector<int> indicesI(lineWidth);
+    std::vector<int> indicesJ(lineWidth);
+
+    int lineNum = 0;
+    while (!lineCoordinates.empty())
+    {
+        lineNum++;
+        std::pair<int, int> startCoordinates = lineCoordinates.front();
+
+        int x0 = startCoordinates.first;
+        int y0 = startCoordinates.second;
+
+        if ( fabs(a) > fabs(b) )
+        {
+            xflag = 1;
+            dx0 = a > 0 ? 1 : -1;
+            dy0 = (int)( b*(1 << shift)/fabs(a) + 0.5);
+            y0 = (y0 << shift) + (1 << (shift-1));
+        }
+        else
+        {
+            xflag = 0;
+            dy0 = b > 0 ? 1 : -1;
+            dx0 = (int)( a*(1 << shift)/fabs(b) + 0.5);
+            x0 = (x0 << shift) + (1 << (shift-1));
+        }
+
+        int numOfGaps = 0;
+        bool useLine = true;
+        for ( int k = 0; k < 2; k++ )
+        {
+            int gap = 0, x = x0, y = y0, dx = dx0, dy = dy0;
+
+            if ( k > 0 )
+                dx = -dx, dy = -dy;
+
+            // walk along the line using fixed-point arithmetics,
+            // stop at the image border or in case of too big gap
+            for ( ;; x += dx, y += dy )
+            {
+                find_indices(indicesI, indicesJ, shift, xflag, x, y, lineWidth);
+
+                remove_points(lineCoordinates, indicesI, indicesJ);
+
+                // for each non-zero point:
+                //    update line end,
+                //    clear the mask element
+                //    reset the gap
+                if ( isData(mImage, indicesI, indicesJ, cols, rows) )
+                {
+                    if (gap > gapSize)
+                    {
+                        numOfGaps++;
+                        if (numOfGaps > maxNumOfGaps)
+                        {
+                            useLine = false;
+                            break;
+                        }
+                    }
+                    gap = 0;
+                    line_end[k].y = indicesI[0];
+                    line_end[k].x = indicesJ[0];
+                }
+                else if ( ++gap > lineGap )
+                {
+                    break;
+                }
+            }
+        }
+
+        bool good_line = abs(line_end[1].x - line_end[0].x) >= lineLength ||
+                abs(line_end[1].y - line_end[0].y) >= lineLength;
+
+        if (good_line && useLine)
+        {
+            Segment newSegment;
+            newSegment.first.first = line_end[0].x;
+            newSegment.first.second = line_end[0].y;
+            newSegment.second.first = line_end[1].x;
+            newSegment.second.second = line_end[1].y;
+            int limit = 5;
+            bool add = true;
+            if (!newSegments.empty())
+            {
+                add = false;
+                const Segment lastSegment = newSegments.back();
+                if (!segmentContainsPoint(lastSegment, newSegment.first, xflag, limit) &&
+                    !segmentContainsPoint(lastSegment, newSegment.second, xflag, limit) &&
+                    !segmentContainsPoint(newSegment, lastSegment.first, xflag, limit) &&
+                    !segmentContainsPoint(newSegment, lastSegment.second, xflag, limit))
+                {
+                    add = true;
+                }
+
+                if (add == false)
+                {
+                    if (segmentLenght(lastSegment) < segmentLenght(newSegment))
+                    {
+                        newSegments.pop_back();
+                        add = true;
+                    }
+                }
+            }
+            if (add)
+            {
+                newSegments.push_back(newSegment);
+            }
+        }
+    }
+    segments.insert(segments.end(), newSegments.begin(), newSegments.end());
+}

Added: grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/linesegmentsextractor.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,50 @@
+#ifndef LILESEGMENTSEXTRACTOR_H
+#define LILESEGMENTSEXTRACTOR_H
+
+
+#include "houghparameters.h"
+#include "matrix.h"
+
+#include <vector>
+#include <list>
+
+typedef std::pair<int, int> Coordinates;
+typedef std::pair< Coordinates, Coordinates > Segment;
+typedef std::vector< Segment > SegmentList;
+typedef std::list< std::pair<int, int> > LineCoordinates;
+
+class LineSegmentsExtractor
+{
+public:
+    typedef double value_type;
+    typedef matrix::Matrix<value_type> Matrix;
+
+    /**
+      \param image should exist during existence of LineSegmentsExtractor
+      \param lineCoordinates will be copied to internal variable
+      */
+    LineSegmentsExtractor(const Matrix& image,
+                          const ExtractParametres& parametres)
+        : mImage(image),
+          gapSize(parametres.gapSize), maxNumOfGaps(parametres.maxNumOfGaps),
+          lineGap(parametres.maxGap), lineLength(parametres.lineLength),
+          lineWidth(parametres.lineWidth)
+    {}
+
+    /**
+      \param lineCoordinates list of lines
+      \param orient orientation of lines
+      \param[out] segments extracted segments will be added to this list
+      */
+    void extract(LineCoordinates lineCoordinates, const double orient, SegmentList& segments);
+
+private:
+    const Matrix &mImage;
+    int gapSize;
+    int maxNumOfGaps;
+    int lineGap;
+    int lineLength;
+    int lineWidth;
+};
+
+#endif // LILESEGMENTSEXTRACTOR_H

Added: grass-addons/grass7/grass7/raster/r.houghtransform/main.cpp
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/main.cpp	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/main.cpp	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,209 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.houghtransform
+ * AUTHOR(S):    Anna Kratochvilova - kratochanna gmail.com
+ *               Vaclav Petras - wenzeslaus gmail.com
+ *
+ * PURPOSE:      Line segment extraction using Hough transformation.
+ *
+ * COPYRIGHT:    (C) 2012 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *   	    	 License (>=v2). Read the file COPYING that comes with GRASS
+ *   	    	 for details.
+ *
+ *****************************************************************************/
+
+#include "hough.h"
+
+extern "C" {
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include <grass/gmath.h>
+}
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/**
+
+  \todo Floats are used instead of doubles.
+  \todo Be able to work with FCELL (and CELL?).
+  */
+int main(int argc, char *argv[])
+{
+    struct Cell_head cell_head;	/* it stores region information,
+                                   and header information of rasters */
+    char *name;			/* input raster name */
+
+    char *mapset;		/* mapset name */
+
+    char *result;		/* output raster name */
+
+    int nrows, ncols;
+
+    struct GModule *module;	/* GRASS module for parsing arguments */
+
+    /* options */
+    struct Option *input, *output, *anglesOption, *houghImageNameOption,
+            *angleWidthOption,
+            *minGapOption, *maxNumberOfGapsOption,
+            *maxLinesOption, *maxGapOption, *minSegmentLengthOption,
+            *lineWidthOption;
+
+    /* initialize GIS environment */
+    G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */
+
+    /* initialize module */
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("hought"));
+    G_add_keyword(_("ht"));
+    module->description =
+            _("Perform Hough transformation and extracts line segments from image."
+              " Region shall be set to input map."
+              " Can work only on small images since map is loaded into memory.");
+
+    /* Define the different options as defined in gis.h */
+    input = G_define_standard_option(G_OPT_R_INPUT);
+
+    output = G_define_standard_option(G_OPT_V_OUTPUT);
+
+    anglesOption = G_define_standard_option(G_OPT_R_INPUT);
+    anglesOption->key = "angles";
+    anglesOption->required = NO;
+    anglesOption->description = _("Name of input image with angles from i.edge.");
+
+    houghImageNameOption = G_define_standard_option(G_OPT_R_OUTPUT);
+    houghImageNameOption->key = "hough_image";
+    houghImageNameOption->required = NO;
+    houghImageNameOption->description = _("Name of output image containing Hough transform");
+
+    angleWidthOption = G_define_option();
+    angleWidthOption->key = "angle_width";
+    angleWidthOption->type = TYPE_INTEGER;
+    angleWidthOption->required = NO;
+    angleWidthOption->multiple = NO;
+    angleWidthOption->description = _("Width of circle sector (only when you provide angle map)");
+    angleWidthOption->answer = const_cast<char *>("5");
+
+    // this option will become max peaks number to find in HT
+    maxLinesOption = G_define_option();
+    maxLinesOption->key = "lines_number";
+    maxLinesOption->type = TYPE_INTEGER;
+    maxLinesOption->required = NO;
+    maxLinesOption->multiple = NO;
+    maxLinesOption->label = _("Approximate number of line segments");
+    maxLinesOption->description = _(
+                "This number represents"
+                " maximal number of line candidates"
+                " detected in Hough transform image."
+                " Final number of line segments can be"
+                " smaller or greater.");
+    maxLinesOption->answer = const_cast<char *>("20");
+
+    minGapOption = G_define_option();
+    minGapOption->key = "gap_size";
+    minGapOption->type = TYPE_INTEGER;
+    minGapOption->required = NO;
+    minGapOption->multiple = NO;
+    minGapOption->description = _("Minimal cell count considered as a gap");
+    minGapOption->answer = const_cast<char *>("5");
+
+    maxNumberOfGapsOption = G_define_option();
+    maxNumberOfGapsOption->key = "max_gap_count";
+    maxNumberOfGapsOption->type = TYPE_INTEGER;
+    maxNumberOfGapsOption->required = NO;
+    maxNumberOfGapsOption->multiple = NO;
+    maxNumberOfGapsOption->description = _("Maximal number of gaps in line segment");
+    maxNumberOfGapsOption->answer = const_cast<char *>("5");
+
+    maxGapOption = G_define_option();
+    maxGapOption->key = "max_gap";
+    maxGapOption->type = TYPE_INTEGER;
+    maxGapOption->required = NO;
+    maxGapOption->multiple = NO;
+    maxGapOption->description = _("Maximum gap in pixels");
+    maxGapOption->answer = const_cast<char *>("5");
+
+    minSegmentLengthOption = G_define_option();
+    minSegmentLengthOption->key = "min_segment_length";
+    minSegmentLengthOption->type = TYPE_INTEGER;
+    minSegmentLengthOption->required = NO;
+    minSegmentLengthOption->multiple = NO;
+    minSegmentLengthOption->description = _("Minimal length of line segment");
+    minSegmentLengthOption->answer = const_cast<char *>("50");
+
+    lineWidthOption = G_define_option();
+    lineWidthOption->key = "line_width";
+    lineWidthOption->type = TYPE_INTEGER;
+    lineWidthOption->required = NO;
+    lineWidthOption->multiple = NO;
+    lineWidthOption->description = _("Expected width of line (used for searching segments)");
+    lineWidthOption->answer = const_cast<char *>("3");
+
+    /* options and flags parser */
+    if (G_parser(argc, argv))
+        exit(EXIT_FAILURE);
+
+    /* stores options and flags to variables */
+    result = output->answer;
+    name = input->answer;
+
+
+    HoughParametres houghParametres;
+    houghParametres.maxPeaksNum = atoi(maxLinesOption->answer);
+    houghParametres.threshold = 10; // TODO: consider option
+    houghParametres.angleWidth = atoi(angleWidthOption->answer);
+    houghParametres.sizeOfNeighbourhood = 1; // TODO: consider option
+
+    ExtractParametres extractParametres;
+    extractParametres.gapSize = atoi(minGapOption->answer);
+    extractParametres.maxGap = atoi(maxGapOption->answer);
+    extractParametres.maxNumOfGaps = atoi(maxNumberOfGapsOption->answer);
+    extractParametres.lineLength = atoi(minSegmentLengthOption->answer);
+    extractParametres.lineWidth = atoi(lineWidthOption->answer);
+
+    /* returns NULL if the map was not found in any mapset,
+     * mapset name otherwise */
+    mapset = (char *)G_find_raster2(name, "");
+    if (mapset == NULL)
+        G_fatal_error(_("Raster map <%s> not found"), name);
+
+    /* determine the inputmap type (CELL/FCELL/DCELL) */
+    //data_type = Rast_map_type(name, mapset);
+
+    //    struct Cell_head templCellhd;
+
+    //    Rast_get_cellhd(name, mapset, &cellhd);
+    //    Rast_get_cellhd(first_map_R_name, first_map_R_mapset, &cellhd_zoom1);
+
+    /* controlling, if we can open input raster */
+    Rast_get_cellhd(name, mapset, &cell_head);
+
+    G_debug(3, "number of rows %d", cell_head.rows);
+
+    nrows = Rast_window_rows();
+
+    ncols = Rast_window_cols();
+
+    /* **** */
+
+    hough_peaks(houghParametres, extractParametres, name, mapset, nrows, ncols, anglesOption->answer, houghImageNameOption->answer, result);
+
+    /* **** */
+
+    /* memory cleanup */
+    G_free(name);
+
+    /* add command line incantation to history file */
+    //    Rast_short_history(templName, "raster", &history);
+    //    Rast_command_history(&history);
+    //    Rast_write_history(templName, &history);
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.houghtransform/matrix.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/matrix.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/matrix.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,200 @@
+#ifndef MATRIX_H
+#define MATRIX_H
+
+#include <vector>
+#include <algorithm>
+#include <limits>
+#include <cmath>
+
+/* mimics Octave matrices and other classes */
+
+namespace matrix {
+
+template <typename T>
+class Matrix
+{
+public:
+    typedef T value_type;
+
+    Matrix(size_t r, size_t c, value_type val = 0)
+        : mRows(r), mCols(c)
+    {
+        resize(r, c, val);
+    }
+    Matrix() : mRows(0), mCols(0) {}
+
+    void resize(size_t r, size_t c, value_type val = 0)
+    {
+        mRows = r;
+        mCols = c;
+        std::vector<value_type> row;
+        row.resize(c, val);
+        mat.resize(r, row);
+    }
+
+    /**
+
+      if (r > rows() || c > columns()) error;
+      */
+    value_type& operator ()(size_t r, size_t c)
+    {
+        return mat[r][c];
+    }
+    /**
+
+      if (r > rows() || c > columns()) error;
+      */
+    const value_type& operator ()(size_t r, size_t c) const
+    {
+        return mat[r][c];
+    }
+    size_t rows() const { return mRows; }
+    size_t columns() const { return mCols; }
+
+    std::vector<value_type> row_max(std::vector<size_t>& colIndexes) const
+    {
+        std::vector<value_type> ret;
+        ret.reserve(rows());
+        colIndexes.reserve(rows());
+        for (size_t i = 0; i < rows(); ++i)
+        {
+            typename std::vector<value_type>::const_iterator maxe = std::max_element(mat[i].begin(), mat[i].end());
+            value_type max = *maxe;
+            size_t maxi = maxe - mat[i].begin();
+
+            ret.push_back(max);
+            colIndexes.push_back(maxi);
+        }
+        return ret;
+    }
+
+private:
+    std::vector< std::vector<value_type> > mat;
+    size_t mRows;
+    size_t mCols;
+};
+
+template <typename T>
+class ColumnVector
+{
+public:
+    typedef T value_type;
+
+    ColumnVector(Matrix<value_type> mat)
+    {
+        for (size_t i = 0; i < mat.columns(); ++i)
+        {
+            vec.push_back(mat(0, i));
+        }
+    }
+    ColumnVector() {}
+
+    value_type& operator ()(size_t i)
+    {
+        return vec[i];
+    }
+    const value_type& operator ()(size_t i) const
+    {
+        return vec[i];
+    }
+    size_t length() { return vec.size(); }
+
+private:
+    std::vector<value_type> vec;
+};
+
+template <typename T>
+class Range
+{
+public:
+    typedef T value_type;
+
+    Range (double b, double l, double i)
+        : rng_base(b), rng_limit(l), rng_inc(i), rng_nelem(nelem_internal())
+    { }
+
+    Range (double b, double l)
+      : rng_base(b), rng_limit(l), rng_inc(1),
+        rng_nelem(nelem_internal()) { }
+
+    Matrix<value_type> matrix_value() const
+    {
+        Matrix<value_type> cache;
+        //if (rng_nelem > 0 && cache.nelem () == 0)
+          //{
+            cache.resize(1, rng_nelem);
+            double b = rng_base;
+            double increment = rng_inc;
+            for (size_t i = 0; i < rng_nelem; i++)
+              cache(0, i) = b + i * increment;
+
+            // On some machines (x86 with extended precision floating point
+            // arithmetic, for example) it is possible that we can overshoot
+            // the limit by approximately the machine precision even though
+            // we were very careful in our calculation of the number of
+            // elements.
+
+            if ((rng_inc > 0 && cache(0, rng_nelem-1) > rng_limit)
+                || (rng_inc < 0 && cache(0, rng_nelem-1) < rng_limit))
+              cache(0, rng_nelem-1) = rng_limit;
+        //  }
+        return cache;
+    }
+
+private:
+    /* from Octave source codes */
+    size_t nelem_internal() const
+    {
+      size_t retval = -1;
+
+      if (rng_inc == 0
+          || (rng_limit > rng_base && rng_inc < 0)
+          || (rng_limit < rng_base && rng_inc > 0))
+        {
+          retval = 0;
+        }
+      else
+        {
+          // double ct = 3.0 * std::numeric_limits<double>::epsilon(); // FIXME: not used
+          // was DBL_EPSILON;
+
+          // double tmp = tfloor ((rng_limit - rng_base + rng_inc) / rng_inc, ct); // octave code
+          double tmp = floor ((rng_limit - rng_base + rng_inc) / rng_inc);
+
+          size_t n_elt = (tmp > 0.0 ? static_cast<size_t> (tmp) : 0);
+
+          // If the final element that we would compute for the range is
+          // equal to the limit of the range, or is an adjacent floating
+          // point number, accept it.  Otherwise, try a range with one
+          // fewer element.  If that fails, try again with one more
+          // element.
+          //
+          // I'm not sure this is very good, but it seems to work better than
+          // just using tfloor as above.  For example, without it, the
+          // expression 1.8:0.05:1.9 fails to produce the expected result of
+          // [1.8, 1.85, 1.9].
+
+          // octave code
+          // if (! teq (rng_base + (n_elt - 1) * rng_inc, rng_limit))
+          //   {
+          //     if (teq (rng_base + (n_elt - 2) * rng_inc, rng_limit))
+          //       n_elt--;
+          //     else if (teq (rng_base + n_elt * rng_inc, rng_limit))
+          //       n_elt++;
+          //   }
+
+          retval = (n_elt >= std::numeric_limits<size_t>::max () - 1) ? -1 : n_elt;
+        }
+
+      return retval;
+    }
+
+ double rng_base;
+ double rng_limit;
+ double rng_inc;
+ size_t rng_nelem;
+};
+
+}
+
+#endif // MATRIX_H

Added: grass-addons/grass7/grass7/raster/r.houghtransform/r.houghtransform.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.houghtransform/r.houghtransform.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.houghtransform/r.houghtransform.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,19 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.houghtransform</em> is performing line extraction from edges in 
+a raster map using the Hough transform.
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.thin.html">r.thin</a>
+</em>
+
+
+<h2>AUTHORS</h2>
+
+Anna Kratochvilova,
+Vaclav Petras
+
+<p><i>Last changed: $Date: 2012-08-02 12:35:50 +0200 (Thu, 02 Aug 2012) $</i>
+

Added: grass-addons/grass7/grass7/raster/r.hydrodem/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.hydrodem
+
+LIBES     = $(SEGMENTLIB) $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(SEGMENTDEP) $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.hydrodem/bseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/bseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/bseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,159 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int bseg_open(BSEG *bseg, int srows, int scols, int nsegs_in_memory)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    bseg->filename = NULL;
+    bseg->fd = -1;
+    bseg->name = NULL;
+    bseg->mapset = NULL;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("bseg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (0 > (errflag = segment_format(fd, Rast_window_rows(),
+				      Rast_window_cols(), srows, scols,
+				      sizeof(char)))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("bseg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("bseg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("bseg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(bseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("bseg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("bseg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    bseg->filename = filename;
+    bseg->fd = fd;
+    return 0;
+}
+
+int bseg_close(BSEG *bseg)
+{
+    segment_release(&(bseg->seg));
+    close(bseg->fd);
+    unlink(bseg->filename);
+    if (bseg->name) {
+	G_free(bseg->name);
+	bseg->name = NULL;
+    }
+    if (bseg->mapset) {
+	G_free(bseg->mapset);
+	bseg->mapset = NULL;
+    }
+    return 0;
+}
+
+int bseg_put(BSEG *bseg, char *value, int row, int col)
+{
+    if (segment_put(&(bseg->seg), value, row, col) < 0) {
+	G_warning(_("bseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int bseg_put_row(BSEG *bseg, char *value, int row)
+{
+    if (segment_put_row(&(bseg->seg), value, row) < 0) {
+	G_warning(_("bseg_put_row(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int bseg_get(BSEG *bseg, char *value, int row, int col)
+{
+    if (segment_get(&(bseg->seg), value, row, col) < 0) {
+	G_warning(_("bseg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+
+int bseg_read_raster(BSEG *bseg, char *map_name, char *mapset)
+{
+    int row, nrows;
+    int col, ncols;
+    int map_fd;
+    CELL *buffer;
+    char cbuf;
+
+    bseg->name = NULL;
+    bseg->mapset = NULL;
+
+    map_fd = Rast_open_old(map_name, mapset);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    buffer = Rast_allocate_c_buf();
+    for (row = 0; row < nrows; row++) {
+	Rast_get_c_row(map_fd, buffer, row);
+	for (col = ncols; col >= 0; col--) {
+	    cbuf = (char) buffer[col];
+	    bseg_put(bseg, &cbuf, row, col);
+	}
+    }
+
+    Rast_close(map_fd);
+    G_free(buffer);
+
+    bseg->name = G_store(map_name);
+    bseg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int bseg_write_raster(BSEG *bseg, char *map_name)
+{
+    int map_fd;
+    int row, nrows;
+    int col, ncols;
+    CELL *buffer;
+    char value;
+
+    map_fd = Rast_open_c_new(map_name);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    buffer = Rast_allocate_c_buf();
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 1);
+	for (col = 0; col < ncols; col++) {
+	    bseg_get(bseg, &value, row, col);
+	    buffer[col] = value;
+	}
+	Rast_put_row(map_fd, buffer, CELL_TYPE);
+    }
+    G_percent(row, nrows, 1);    /* finish it */
+    G_free(buffer);
+    Rast_close(map_fd);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/close.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/close.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/close.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,57 @@
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int close_map(char *ele_rast, int ele_map_type)
+{
+    int ele_fd, r, c;
+    void *ele_buf, *ele_ptr;
+    struct History history;
+    size_t ele_size;
+    CELL ele_val;
+
+    G_message(_("Write conditioned DEM"));
+
+    ele_fd = Rast_open_new(ele_rast, ele_map_type);
+    ele_size = Rast_cell_size(ele_map_type);
+    ele_buf = Rast_allocate_buf(ele_map_type);
+
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+
+	Rast_set_null_value(ele_buf, ncols, ele_map_type);	/* reset row to all NULL */
+
+	ele_ptr = ele_buf;
+
+	for (c = 0; c < ncols; c++) {
+	    cseg_get(&ele, &ele_val, r, c);
+
+	    if (!Rast_is_c_null_value(&ele_val)) {
+
+		switch (ele_map_type) {
+		case CELL_TYPE:
+		    *((CELL *) ele_ptr) = ele_val;
+		    break;
+		case FCELL_TYPE:
+		    *((FCELL *) ele_ptr) = (FCELL) ele_val / ele_scale;
+		    break;
+		case DCELL_TYPE:
+		    *((DCELL *) ele_ptr) = (DCELL) ele_val / ele_scale;
+		    break;
+		}
+	    }
+	    ele_ptr = G_incr_void_ptr(ele_ptr, ele_size);
+	}
+	Rast_put_row(ele_fd, ele_buf, ele_map_type);
+    }
+    G_percent(nrows, nrows, 2);	/* finish it */
+
+    Rast_close(ele_fd);
+    G_free(ele_buf);
+    Rast_short_history(ele_rast, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(ele_rast, &history);
+
+    return 1;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/cseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/cseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/cseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,154 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int cseg_open(CSEG *cseg, int srows, int scols, int nsegs_in_memory)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    cseg->filename = NULL;
+    cseg->fd = -1;
+    cseg->name = NULL;
+    cseg->mapset = NULL;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("cseg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (0 >
+	(errflag =
+	 segment_format(fd, Rast_window_rows(), Rast_window_cols(), srows, scols,
+			sizeof(CELL)))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("cseg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("cseg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("cseg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(cseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("cseg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("cseg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    cseg->filename = filename;
+    cseg->fd = fd;
+    return 0;
+}
+
+int cseg_close(CSEG *cseg)
+{
+    segment_release(&(cseg->seg));
+    close(cseg->fd);
+    unlink(cseg->filename);
+    if (cseg->name) {
+	G_free(cseg->name);
+	cseg->name = NULL;
+    }
+    if (cseg->mapset) {
+	G_free(cseg->mapset);
+	cseg->mapset = NULL;
+    }
+    return 0;
+}
+
+int cseg_put(CSEG *cseg, CELL *value, int row, int col)
+{
+    if (segment_put(&(cseg->seg), value, row, col) < 0) {
+	G_warning(_("cseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int cseg_put_row(CSEG *cseg, CELL *value, int row)
+{
+    if (segment_put_row(&(cseg->seg), value, row) < 0) {
+	G_warning(_("cseg_put_row(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int cseg_get(CSEG *cseg, CELL *value, int row, int col)
+{
+    if (segment_get(&(cseg->seg), value, row, col) < 0) {
+	G_warning(_("cseg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int cseg_read_raster(CSEG *cseg, char *map_name, char *mapset)
+{
+    int row, nrows;
+    int map_fd;
+    CELL *buffer;
+
+    cseg->name = NULL;
+    cseg->mapset = NULL;
+
+    map_fd = Rast_open_old(map_name, mapset);
+    nrows = Rast_window_rows();
+    buffer = Rast_allocate_c_buf();
+    for (row = 0; row < nrows; row++) {
+	Rast_get_c_row(map_fd, buffer, row);
+	if (segment_put_row(&(cseg->seg), buffer, row) < 0) {
+	    G_free(buffer);
+	    Rast_close(map_fd);
+	    G_warning(_("cseg_read_cell(): unable to segment put row for <%s> in <%s>"),
+		    map_name, mapset);
+	    return (-1);
+	}
+    }
+
+    Rast_close(map_fd);
+    G_free(buffer);
+
+    cseg->name = G_store(map_name);
+    cseg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int cseg_write_raster(CSEG *cseg, char *map_name)
+{
+    int map_fd;
+    int row, nrows;
+    CELL *buffer;
+
+    map_fd = Rast_open_c_new(map_name);
+    nrows = Rast_window_rows();
+    buffer = Rast_allocate_c_buf();
+    segment_flush(&(cseg->seg));
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 1);
+	segment_get_row(&(cseg->seg), buffer, row);
+	Rast_put_row(map_fd, buffer, CELL_TYPE);
+    }
+    G_percent(row, nrows, 1);    /* finish it */
+    G_free(buffer);
+    Rast_close(map_fd);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/do_astar.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/do_astar.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/do_astar.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,356 @@
+#include <stdlib.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+#define GET_PARENT(c) ((unsigned int)(((c) - 2) >> 2) + 1)
+#define GET_CHILD(p) ((unsigned int)((p) << 2) - 2)
+
+#define HEAP_CMP(a, b) (((a)->ele < (b)->ele) ? 1 : \
+                       (((a)->ele > (b)->ele) ? 0 : \
+		       (((a)->added < (b)->added) ? 1 : 0)))
+
+
+struct heap_point heap_drop(void);
+
+double get_slope(CELL, CELL, double);
+
+int do_astar(void)
+{
+    int r, c, r_nbr, c_nbr, ct_dir;
+    unsigned int count;
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+    CELL ele_val, ele_down, ele_nbr[8];
+    char is_bottom;
+    char asp_val, asp_val_this;
+    char flag_value, is_in_list, is_worked;
+    struct heap_point heap_p;
+    /* sides
+     * |7|1|4|
+     * |2| |3|
+     * |5|0|6|
+     */
+    int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1};
+    int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2};
+    double dx, dy, dist_to_nbr[8], ew_res, ns_res;
+    double slope[8];
+    int skip_diag;
+    struct Cell_head window;
+
+    count = 0;
+
+    first_cum = n_points;
+
+    sinks = first_sink = NULL;
+    n_sinks = 0;
+
+    G_message(_("A* Search..."));
+
+    Rast_get_window(&window);
+
+    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	/* get r, c (r_nbr, c_nbr) for neighbours */
+	r_nbr = nextdr[ct_dir];
+	c_nbr = nextdc[ct_dir];
+	/* account for rare cases when ns_res != ew_res */
+	dy = abs(r_nbr) * window.ns_res;
+	dx = abs(c_nbr) * window.ew_res;
+	if (ct_dir < 4)
+	    dist_to_nbr[ct_dir] = dx + dy;
+	else
+	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
+    }
+    ew_res = window.ew_res;
+    ns_res = window.ns_res;
+
+    while (heap_size > 0) {
+	G_percent(count++, n_points, 1);
+	if (count > n_points)
+	    G_fatal_error(_("BUG in A* Search: %d surplus points"),
+	                  heap_size);
+
+	if (heap_size > n_points)
+	    G_fatal_error
+		(_("BUG in A* Search: too many points in heap %d, should be %d"),
+		 heap_size, n_points);
+
+	heap_p = heap_drop();
+
+	/* flow accumulation order is not needed */
+	r = heap_p.r;
+	c = heap_p.c;
+
+	first_cum--;
+	bseg_get(&bitflags, &flag_value, r, c);
+	FLAG_SET(flag_value, WORKEDFLAG);
+	bseg_put(&bitflags, &flag_value, r, c);
+
+	ele_val = ele_down = heap_p.ele;
+	is_bottom = 0;
+	bseg_get(&draindir, &asp_val_this, r, c);
+	if (asp_val_this > 0 && !FLAG_GET(flag_value, EDGEFLAG)) {
+	    r_nbr = r + asp_r[(int)asp_val_this];
+	    c_nbr = c + asp_c[(int)asp_val_this];
+	    cseg_get(&ele, &ele_down, r_nbr, c_nbr);
+	    if (ele_down > ele_val)
+		is_bottom = 1;
+	}
+
+	for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	    /* get r, c (r_nbr, c_nbr) for neighbours */
+	    r_nbr = r + nextdr[ct_dir];
+	    c_nbr = c + nextdc[ct_dir];
+	    slope[ct_dir] = ele_nbr[ct_dir] = 0;
+
+	    /* check that neighbour is within region */
+	    if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
+		continue;
+
+	    bseg_get(&bitflags, &flag_value, r_nbr, c_nbr);
+	    is_in_list = FLAG_GET(flag_value, INLISTFLAG);
+	    is_worked = FLAG_GET(flag_value, WORKEDFLAG);
+	    skip_diag = 0;
+
+	    /* avoid diagonal flow direction bias */
+	    if (!is_worked) {
+		cseg_get(&ele, &ele_nbr[ct_dir], r_nbr, c_nbr);
+		slope[ct_dir] = get_slope(ele_val, ele_nbr[ct_dir],
+		                          dist_to_nbr[ct_dir]);
+	    }
+
+	    if (!is_in_list) {
+		if (ct_dir > 3 && slope[ct_dir] > 0) {
+		    if (slope[nbr_ew[ct_dir]] > 0) {
+			/* slope to ew nbr > slope to center */
+			if (slope[ct_dir] < get_slope(ele_nbr[nbr_ew[ct_dir]],
+			                              ele_nbr[ct_dir], ew_res))
+			    skip_diag = 1;
+		    }
+		    if (!skip_diag && slope[nbr_ns[ct_dir]] > 0) {
+			/* slope to ns nbr > slope to center */
+			if (slope[ct_dir] < get_slope(ele_nbr[nbr_ns[ct_dir]],
+			                              ele_nbr[ct_dir], ns_res))
+			    skip_diag = 1;
+		    }
+		}
+	    }
+
+	    if (is_in_list == 0 && skip_diag == 0) {
+		asp_val = drain[r_nbr - r + 1][c_nbr - c + 1];
+		heap_add(r_nbr, c_nbr, ele_nbr[ct_dir], asp_val, flag_value);
+
+		if (ele_nbr[ct_dir] < ele_val)
+		    is_bottom = 0;
+	    }
+	    else if (is_in_list && is_worked == 0) {
+		if (FLAG_GET(flag_value, EDGEFLAG)) {
+		    bseg_get(&draindir, &asp_val, r_nbr, c_nbr);
+		    if (asp_val < 0) {
+			/* update edge cell ? no */
+			/* asp_val = drain[r_nbr - r + 1][c_nbr - c + 1]; */
+			/* check if this causes trouble */
+			bseg_put(&draindir, &asp_val, r_nbr, c_nbr);
+
+			if (ele_nbr[ct_dir] < ele_val)
+			    is_bottom = 0;
+		    }
+		}
+		else if (FLAG_GET(flag_value, DEPRFLAG)) {
+		    G_debug(3, "real depression");
+		    /* neighbour is inside real depression, not yet worked */
+		    bseg_get(&draindir, &asp_val, r_nbr, c_nbr);
+		    if (asp_val == 0 && ele_val <= ele_nbr[ct_dir]) {
+			asp_val = drain[r_nbr - r + 1][c_nbr - c + 1];
+			bseg_put(&draindir, &asp_val, r_nbr, c_nbr);
+			FLAG_UNSET(flag_value, DEPRFLAG);
+			bseg_put(&bitflags, &flag_value, r_nbr, c_nbr);
+		    }
+		}
+	    }
+	}    /* end neighbours */
+
+
+	if (is_bottom) {
+	    /* add sink bottom */
+	    /* process upstream */
+	    if (1) {
+		if (first_sink) {
+		    sinks->next =
+			(struct sink_list *)
+			G_malloc(sizeof(struct sink_list));
+		    sinks = sinks->next;
+		}
+		/* first sink */
+		else {
+		    first_sink =
+			(struct sink_list *)
+			G_malloc(sizeof(struct sink_list));
+		    sinks = first_sink;
+		}
+		sinks->next = NULL;
+	    }
+	    /* process downstream */
+	    if (0) {
+		sinks =
+		    (struct sink_list *)
+		    G_malloc(sizeof(struct sink_list));
+		sinks->next = first_sink;
+		first_sink = sinks;
+	    }
+	    sinks->r = r;
+	    sinks->c = c;
+	    n_sinks++;
+	}
+    }    /* end A* search */
+
+    G_percent(n_points, n_points, 1);	/* finish it */
+
+    if (first_cum)
+	G_warning(_("processed points mismatch of %u"), first_cum);
+
+    return 1;
+}
+
+/*
+ * compare function for heap
+ * returns 1 if point1 < point2 else 0
+ */
+
+static int heap_cmp(struct heap_point *a, struct heap_point *b)
+{
+    if (a->ele < b->ele)
+	return 1;
+    else if (a->ele == b->ele) {
+	if (a->added < b->added)
+	    return 1;
+    }
+    return 0;
+}
+
+int sift_up(unsigned int start, struct heap_point child_p)
+{
+    unsigned int parent, child;
+    struct heap_point heap_p;
+
+    child = start;
+
+    while (child > 1) {
+	parent = GET_PARENT(child);
+
+	seg_get(&search_heap, (char *)&heap_p, 0, parent);
+
+	/* push parent point down if child is smaller */
+	if (heap_cmp(&child_p, &heap_p)) {
+	    seg_put(&search_heap, (char *)&heap_p, 0, child);
+	    child = parent;
+	}
+	else
+	    /* no more sifting up, found new slot for child */
+	    break;
+    }
+
+    /* add child to heap */
+    seg_put(&search_heap, (char *)&child_p, 0, child);
+
+    return 0;
+}
+
+/*
+ * add item to heap
+ * returns heap_size
+ */
+unsigned int heap_add(int r, int c, CELL ele, char asp, char flag_value)
+{
+    struct heap_point heap_p;
+
+    /* add point to next free position */
+
+    heap_size++;
+
+    if (heap_size > n_points)
+	G_fatal_error(_("Heapsize too large"));
+
+    heap_p.r = r;
+    heap_p.c = c;
+    heap_p.ele = ele;
+    heap_p.added = nxt_avail_pt;
+
+    bseg_put(&draindir, &asp, r, c);
+    FLAG_SET(flag_value, INLISTFLAG);
+    bseg_put(&bitflags, &flag_value, r, c);
+
+    nxt_avail_pt++;
+
+    /* sift up: move new point towards top of heap */
+
+    sift_up(heap_size, heap_p);
+
+    return heap_size;
+}
+
+/*
+ * drop item from heap
+ * returns heap size
+ */
+struct heap_point heap_drop(void)
+{
+    unsigned int child, childr, parent;
+    unsigned int i;
+    struct heap_point child_p, childr_p, last_p, root_p;
+
+    seg_get(&search_heap, (char *)&last_p, 0, heap_size);
+    seg_get(&search_heap, (char *)&root_p, 0, 1);
+
+    if (heap_size == 1) {
+	heap_size = 0;
+	return root_p;
+    }
+
+    parent = 1;
+    while ((child = GET_CHILD(parent)) <= heap_size) {
+
+	seg_get(&search_heap, (char *)&child_p, 0, child);
+
+	if (child < heap_size) {
+	    childr = child + 1;
+	    i = child + 4;
+	    while (childr <= heap_size && childr < i) {
+		seg_get(&search_heap, (char *)&childr_p, 0, childr);
+		if (heap_cmp(&childr_p, &child_p)) {
+		    child = childr;
+		    child_p = childr_p;
+		}
+		childr++;
+	    }
+	}
+	if (heap_cmp(&last_p, &child_p)) {
+	    break;
+	}
+
+	/* move hole down */
+	seg_put(&search_heap, (char *)&child_p, 0, parent);
+	parent = child;
+    }
+
+    /* fill hole */
+    if (parent < heap_size) {
+	seg_put(&search_heap, (char *)&last_p, 0, parent);
+    }
+
+    /* the actual drop */
+    heap_size--;
+
+    return root_p;
+}
+
+double get_slope(CELL ele, CELL up_ele, double dist)
+{
+    if (ele >= up_ele)
+	return 0.0;
+    else
+	return (double)(up_ele - ele) / dist;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/dseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/dseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/dseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,156 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int dseg_open(DSEG *dseg, int srows, int scols, int nsegs_in_memory)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    dseg->filename = NULL;
+    dseg->fd = -1;
+    dseg->name = NULL;
+    dseg->mapset = NULL;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("dseg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (0 >
+	(errflag =
+	 segment_format(fd, Rast_window_rows(), Rast_window_cols(), srows, scols,
+			sizeof(DCELL)))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("dseg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("dseg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("dseg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(dseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("dseg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("dseg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    dseg->filename = filename;
+    dseg->fd = fd;
+    return 0;
+}
+
+int dseg_close(DSEG *dseg)
+{
+    segment_release(&(dseg->seg));
+    close(dseg->fd);
+    unlink(dseg->filename);
+    if (dseg->name) {
+	G_free(dseg->name);
+	dseg->name = NULL;
+    }
+    if (dseg->mapset) {
+	G_free(dseg->mapset);
+	dseg->mapset = NULL;
+    }
+    return 0;
+}
+
+int dseg_put(DSEG *dseg, DCELL *value, int row, int col)
+{
+    if (segment_put(&(dseg->seg), (DCELL *) value, row, col) < 0) {
+	G_warning(_("dseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int dseg_put_row(DSEG *dseg, DCELL *value, int row)
+{
+    if (segment_put_row(&(dseg->seg), (DCELL *) value, row) < 0) {
+	G_warning(_("dseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int dseg_get(DSEG *dseg, DCELL *value, int row, int col)
+{
+    if (segment_get(&(dseg->seg), (DCELL *) value, row, col) < 0) {
+	G_warning(_("dseg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int dseg_read_raster(DSEG *dseg, char *map_name, char *mapset)
+{
+    int row, nrows, ncols;
+    int map_fd;
+    DCELL *dbuffer;
+
+    dseg->name = NULL;
+    dseg->mapset = NULL;
+
+    map_fd = Rast_open_old(map_name, mapset);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    dbuffer = Rast_allocate_d_buf();
+    for (row = 0; row < nrows; row++) {
+	Rast_get_d_row(map_fd, dbuffer, row);
+	if (segment_put_row(&(dseg->seg), (DCELL *) dbuffer, row) < 0) {
+	    G_free(dbuffer);
+	    Rast_close(map_fd);
+	    G_warning(_("dseg_read_raster(): unable to segment put row for <%s> in <%s>"),
+		    map_name, mapset);
+	    return (-1);
+	}
+    }
+
+    Rast_close(map_fd);
+    G_free(dbuffer);
+
+    dseg->name = G_store(map_name);
+    dseg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int dseg_write_cellfile(DSEG *dseg, char *map_name)
+{
+    int map_fd;
+    int row, nrows, ncols;
+    DCELL *dbuffer;
+
+    map_fd = Rast_open_new(map_name, DCELL_TYPE);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    dbuffer = Rast_allocate_d_buf();
+    segment_flush(&(dseg->seg));
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 1);
+	segment_get_row(&(dseg->seg), (DCELL *) dbuffer, row);
+	Rast_put_row(map_fd, dbuffer, DCELL_TYPE);
+    }
+    G_percent(row, nrows, 1);    /* finish it */
+    G_free(dbuffer);
+    Rast_close(map_fd);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/flag.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/flag.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/flag.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,36 @@
+#ifndef __FLAG_H__
+#define __FLAG_H__
+
+/* a set of routines that allow the programmer to "flag" cells in a
+ * raster map. A flag is of type unsigned char, i.e. 8 bits can be set. 
+ *
+ * int flag_set(flag, bitno)
+ *     sets the flag at position bitno to one.
+ *
+ * int flag_unset(flag, bitno)
+ *     sets the flag at position bitno to zero.
+ *
+ * int flag_get(flag, bitno)
+ *     checks if the flag is set at postion bitno.
+ *
+ * Examples:
+ * set flag at position 0: FLAG_SET(flag, 0)
+ * unset (clear) flag at position 7: FLAG_UNSET(flag, 7)
+ * check flag at position 5: is_set_at_5 = FLAG_GET(flag, 5)
+ */
+
+/* flag positions */
+#define NULLFLAG         0      /* elevation is NULL */
+#define EDGEFLAG         1      /* edge cell */
+#define INLISTFLAG       2      /* in open A* list */
+#define WORKEDFLAG       3      /* in closed A* list/ accumulation done */
+#define STREAMFLAG       4      /* stream */
+#define DEPRFLAG         5      /* real depression */
+#define WORKED2FLAG      6      /* extraction done */
+/* last bit is unused */
+
+#define FLAG_SET(flag,bitno) ((flag) |= (1 << (bitno)))
+#define FLAG_UNSET(flag,bitno) ((flag) &= ~(1 << (bitno)))
+#define FLAG_GET(flag,bitno) ((flag) & (1 << (bitno)))
+
+#endif /* __FLAG_H__ */

Added: grass-addons/grass7/grass7/raster/r.hydrodem/hydro_con.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/hydro_con.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/hydro_con.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,878 @@
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+struct ns
+{
+    int r, c;
+    int next_side;
+    int n_ngbrs;
+};
+
+static struct ns *n_stack;
+static int stack_alloc;
+
+static int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+static int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+
+static int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+static int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+
+
+static int count_fill(int peak_r, int peak_c, CELL peak_ele, int *n_splits,
+               CELL *next_ele)
+{
+    int r, c, r_nbr, c_nbr, ct_dir;
+    CELL ele_val, ele_nbr;
+    int n_to_fill;
+    int top, done;
+    char drain_val;
+
+    /* go upstream from spill point */
+    r = peak_r;
+    c = peak_c;
+    ele_val = peak_ele;
+    *n_splits = 0;
+    n_to_fill = 0;
+    /* post-order traversal */
+    /* add spill point as root to stack */
+    top = 0;
+    n_stack[top].r = peak_r;
+    n_stack[top].c = peak_c;
+    n_stack[top].next_side = 0;
+    n_stack[top].n_ngbrs = 0;
+    while (top >= 0) {
+	done = 1;
+	r = n_stack[top].r;
+	c = n_stack[top].c;
+	for (ct_dir = n_stack[top].next_side; ct_dir < sides; ct_dir++) {
+	    r_nbr = r + nextdr[ct_dir];
+	    c_nbr = c + nextdc[ct_dir];
+	    /* check that neighbour is within region */
+	    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
+	        c_nbr < ncols) {
+
+		cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+		bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+		if (drain_val > 0) {
+		    /* contributing cell */
+		    if (r_nbr + asp_r[(int)drain_val] == r &&
+			c_nbr + asp_c[(int)drain_val] == c) {
+
+			/* contributing neighbour is lower than
+			 * spill point, add to stack */
+			if (peak_ele >= ele_nbr) {
+
+			    if (peak_ele > ele_nbr)
+				n_to_fill++;
+			    n_stack[top].next_side = ct_dir + 1;
+			    n_stack[top].n_ngbrs++;
+			    top++;
+			    if (top >= stack_alloc) {
+				stack_alloc += nrows + ncols;
+				n_stack =
+				    (struct ns *)G_realloc(n_stack,
+							   stack_alloc *
+							   sizeof(struct ns));
+			    }
+			    n_stack[top].r = r_nbr;
+			    n_stack[top].c = c_nbr;
+			    n_stack[top].next_side = 0;
+			    n_stack[top].n_ngbrs = 0;
+			    done = 0;
+			    break;
+			}
+			else if (next_ele && peak_ele < ele_nbr) {
+			    if (*next_ele > ele_nbr)
+				*next_ele = ele_nbr;
+			}
+		    }
+		}    /* end contributing */
+		else if (drain_val == 0 && peak_ele > ele_nbr)
+		    /* found bottom of real depression, don't fill */
+		    return -1;
+	    }    /* end in region */
+	}    /* end sides */
+
+	if (done) {
+	    *n_splits += (n_stack[top].n_ngbrs > 1);
+	    n_stack[top].next_side = sides;
+
+	    top--;
+	}
+    }
+    return n_to_fill;
+}
+
+/* detect flat area:
+ * count neighbouring cells with same ele
+ * exclude contributing cells and cell this one is contributing to */
+static int is_flat(int r, int c, CELL this_ele)
+{
+    int r_nbr, c_nbr, ct_dir;
+    CELL ele_nbr;
+    char drain_val, drain_val_nbr;
+    int counter = 0;
+
+    bseg_get(&draindir, &drain_val, r, c);
+
+    if (drain_val < 1)
+	return 0;
+
+    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	r_nbr = r + nextdr[ct_dir];
+	c_nbr = c + nextdc[ct_dir];
+	/* check that neighbour is within region */
+	if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) {
+	    
+	    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+	    bseg_get(&draindir, &drain_val_nbr, r_nbr, c_nbr);
+	    if (drain_val_nbr > 0) {
+		/* not a contributing cell */
+		if (r_nbr + asp_r[(int)drain_val_nbr] != r ||
+		    c_nbr + asp_c[(int)drain_val_nbr] != c) {
+		    /* does not contribute to this cell */
+		    if (r + asp_r[(int)drain_val] != r_nbr ||
+		        c + asp_c[(int)drain_val] != c_nbr) {
+			if (ele_nbr == this_ele)
+			    counter++;
+		    }
+		}
+	    }
+	}
+    }
+
+    return (counter > 0);
+}
+
+static int fill_sink(int peak_r, int peak_c, CELL peak_ele)
+{
+    int r, c, r_nbr, c_nbr, ct_dir;
+    CELL ele_nbr;
+    int n_to_fill = 0;
+    int top, done;
+    char drain_val;
+
+    /* post-order traversal */
+    /* add spill point as root to stack */
+    top = 0;
+    n_stack[top].r = peak_r;
+    n_stack[top].c = peak_c;
+    n_stack[top].next_side = 0;
+    n_stack[top].n_ngbrs = 0;
+    while (top >= 0) {
+	done = 1;
+	r = n_stack[top].r;
+	c = n_stack[top].c;
+	for (ct_dir = n_stack[top].next_side; ct_dir < sides; ct_dir++) {
+	    r_nbr = r + nextdr[ct_dir];
+	    c_nbr = c + nextdc[ct_dir];
+	    /* check that neighbour is within region */
+	    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
+	        c_nbr < ncols) {
+
+		cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+		bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+		if (drain_val > 0) {
+		    /* contributing cell */
+		    if (r_nbr + asp_r[(int)drain_val] == r &&
+			c_nbr + asp_c[(int)drain_val] == c) {
+
+			/* contributing neighbour is lower than
+			 * spill point, add to stack */
+			if (peak_ele >= ele_nbr) {
+
+			    n_to_fill++;
+			    n_stack[top].next_side = ct_dir + 1;
+			    n_stack[top].n_ngbrs++;
+			    top++;
+			    if (top >= stack_alloc) {
+				stack_alloc += nrows + ncols;
+				n_stack =
+				    (struct ns *)G_realloc(n_stack,
+							   stack_alloc *
+							   sizeof(struct ns));
+			    }
+			    n_stack[top].r = r_nbr;
+			    n_stack[top].c = c_nbr;
+			    n_stack[top].next_side = 0;
+			    n_stack[top].n_ngbrs = 0;
+			    done = 0;
+			    break;
+			}
+		    }
+		}		/* end contributing */
+	    }			/* end in region */
+	}			/* end sides */
+
+	if (done) {
+	    cseg_put(&ele, &peak_ele, r, c);
+	    n_stack[top].next_side = sides;
+	    top--;
+	}
+    }
+
+    return n_to_fill;
+}
+
+/* carve channel */
+static int carve(int bottom_r, int bottom_c, CELL bottom_ele,
+          int peak_r, int peak_c)
+{
+    int r, c, r_nbr, c_nbr, carved = 0;
+    char drain_val;
+    int ct_dir;
+    CELL ele_val, ele_nbr;
+    int top, done;
+
+    /* carve upstream from spill point --> */
+    /* post-order traversal */
+    /* add spill point as root to stack */
+    top = 0;
+    n_stack[top].r = peak_r;
+    n_stack[top].c = peak_c;
+    n_stack[top].next_side = 0;
+    n_stack[top].n_ngbrs = 0;
+    while (top >= 0) {
+	done = 1;
+	r = n_stack[top].r;
+	c = n_stack[top].c;
+	cseg_get(&ele, &ele_val, r, c);
+	for (ct_dir = n_stack[top].next_side; ct_dir < sides; ct_dir++) {
+	    r_nbr = r + nextdr[ct_dir];
+	    c_nbr = c + nextdc[ct_dir];
+	    /* check that neighbour is within region */
+	    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
+	        c_nbr < ncols) {
+
+		cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+		bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+		if (drain_val > 0) {
+		    /* contributing cell */
+		    if (r_nbr + asp_r[(int) drain_val] == r &&
+			c_nbr + asp_c[(int) drain_val] == c) {
+
+			/* contributing neighbour is lower than 
+			 * current point, add to stack */
+			if (ele_val > ele_nbr && ele_nbr >= bottom_ele) {
+
+			    n_stack[top].next_side = ct_dir + 1;
+			    n_stack[top].n_ngbrs++;
+			    top++;
+			    if (top >= stack_alloc) {
+				stack_alloc += nrows + ncols;
+				n_stack =
+				    (struct ns *)G_realloc(n_stack,
+							   stack_alloc *
+							   sizeof(struct ns));
+			    }
+			    n_stack[top].r = r_nbr;
+			    n_stack[top].c = c_nbr;
+			    n_stack[top].next_side = 0;
+			    n_stack[top].n_ngbrs = 0;
+			    done = 0;
+			    break;
+			}
+		    }
+		}		/* end contributing */
+	    }			/* end in region */
+	}			/* end sides */
+
+	if (done) {
+	    /* lower all cells to bottom ele
+	     * that have lower lying contributing neighbours */
+	    if (n_stack[top].n_ngbrs > 0)
+		cseg_put(&ele, &bottom_ele, r, c);
+	    n_stack[top].next_side = sides;
+	    top--;
+	}
+    }
+    /* <-- carve upstream from spill point */
+
+    /* carve downstream from sink bottom */
+    bseg_get(&draindir, &drain_val, bottom_r, bottom_c);
+    if (drain_val < 1) {
+	G_warning(_("Can't carve downstream from r %d, c %d"), bottom_r,
+		  bottom_c);
+	return 0;
+    }
+
+    r_nbr = bottom_r + asp_r[(int) drain_val];
+    c_nbr = bottom_c + asp_c[(int) drain_val];
+
+    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+
+    /* go downstream up to peak and down to bottom again */
+    while (ele_nbr >= bottom_ele) {
+	bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+	cseg_put(&ele, &bottom_ele, r_nbr, c_nbr);
+	carved++;
+
+	if (drain_val > 0) {
+	    r_nbr = r_nbr + asp_r[(int) drain_val];
+	    c_nbr = c_nbr + asp_c[(int) drain_val];
+	    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+	}
+	else {
+	    G_debug(2, "%d carved to edge", carved);
+	    return carved;
+	}
+    }
+
+    return carved;
+}
+
+/* remove sinks */
+int hydro_con(void)
+{
+    int counter = 1;
+    int r, c, r_nbr, c_nbr, peak_r, peak_c, noedge, force_carve;
+    CELL ele_val, ele_nbr, ele_last, peak_ele, bottom_ele;
+    int down_uphill, down_downhill, n_cells;
+    struct sink_list *last_sink;
+    char drain_val, flag_value;
+    int n_splits, n_to_fill;
+    int n_filled, n_carved, n_just_a_bit, n_processed;
+    int carve_to_edge, skipme;
+
+    stack_alloc = nrows + ncols;
+
+    n_stack = (struct ns *)G_malloc(stack_alloc * sizeof(struct ns));
+
+    G_message(_("Processing %d sinks"), n_sinks);
+
+    n_filled = n_carved = n_just_a_bit = n_processed = 0;
+
+    while (first_sink) {
+	G_percent(counter++, n_sinks, 1);
+
+	r = first_sink->r;
+	c = first_sink->c;
+
+	cseg_get(&ele, &ele_val, r, c);
+	bottom_ele = ele_val;
+
+	skipme = 0;
+
+	G_debug(1, "get spill point");
+
+	/* go downstream, get spill point */
+	peak_r = r;
+	peak_c = c;
+	bseg_get(&draindir, &drain_val, r, c);
+
+	r_nbr = r + asp_r[(int) drain_val];
+	c_nbr = c + asp_c[(int) drain_val];
+
+	cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+
+	down_uphill = down_downhill = 0;
+	noedge = 1;
+	ele_last = bottom_ele;
+	n_cells = 0;
+	while (ele_nbr >= ele_last) {
+	    n_cells++;
+	    if (ele_nbr > ele_last) {
+		down_uphill = n_cells;
+		peak_r = r_nbr;
+		peak_c = c_nbr;
+	    }
+	    bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+
+	    if (drain_val > 0) {
+		r_nbr = r_nbr + asp_r[(int) drain_val];
+		c_nbr = c_nbr + asp_c[(int) drain_val];
+
+		ele_last = ele_nbr;
+		cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+	    }
+	    else {
+		break;
+	    }
+	}
+
+	cseg_get(&ele, &peak_ele, peak_r, peak_c);
+
+	bseg_get(&bitflags, &flag_value, peak_r, peak_c);
+	noedge = (FLAG_GET(flag_value, EDGEFLAG) == 0);
+	r_nbr = peak_r;
+	c_nbr = peak_c;
+	ele_nbr = peak_ele;
+
+	/* check */
+	if (down_uphill == 0) {
+	    G_debug(2, "sink already processed");
+	    n_processed++;
+
+	    last_sink = first_sink;
+	    first_sink = first_sink->next;
+	    G_free(last_sink);
+	    continue;
+	}
+
+	carve_to_edge = 0;
+	if (noedge) {
+	    G_debug(1, "go downstream from spill point");
+	    /* go downstream from spill point
+	     * until we reach bottom ele again */
+	    while (ele_nbr >= bottom_ele) {
+		if (ele_nbr > bottom_ele)
+		    down_downhill++;
+		bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+
+		/* detect flat area ? */
+
+		if (drain_val > 0) {
+		    r_nbr = r_nbr + asp_r[(int) drain_val];
+		    c_nbr = c_nbr + asp_c[(int) drain_val];
+
+		    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+		}
+		else {
+		    carve_to_edge = 1;
+		    break;
+		}
+	    }
+	}
+	G_debug(1, "%d cells downstream from spill point", down_downhill);
+
+	/* count number of cells
+	 * that would be filled from current spill point upstream */
+	G_debug(1, "count fill");
+	n_to_fill = count_fill(peak_r, peak_c, peak_ele, &n_splits, NULL);
+	
+	skipme = (!do_all && n_to_fill <= size_max);
+
+	nat_thresh = 10;
+
+	/* shallow inland pans:
+	 * - bottom is close to center of the depression 
+	 * - long channel to carve downstream from spill point
+	 * - shallowness */
+	if (n_to_fill > nat_thresh && peak_ele - bottom_ele < 10 &&
+	    sqrt(n_to_fill) / 4.0 < down_uphill)
+	    G_debug(1, "shallow inland pan?");
+
+
+	/*************************/
+	/* set correction method */
+	/*************************/
+
+	/* force carving if edge not past spill point ? */
+	force_carve = (noedge == 0);
+	force_carve = 0;
+	if (!force_carve && (do_all || n_mod_max >= 4) &&
+	    down_uphill + down_downhill <= 4 && 
+	    down_uphill + down_downhill <= n_to_fill)
+	    force_carve = 0;
+
+	/************************************/
+	/* apply selected correction method */
+	/************************************/
+
+	/* force carve channel to edge if edge not past spill point */
+	if (force_carve) {
+	    G_debug(1, "force carve small channel or to edge");
+	    carve(first_sink->r, first_sink->c, bottom_ele,
+	          peak_r, peak_c);
+	    n_carved++;
+	}
+	/* impact reduction algorithm */
+	else if (!skipme) {
+	    int next_r, next_c;
+	    int n_new_splits, is_edge = 0, this_is_flat;
+	    CELL min_bottom_ele, last_ele, next_bottom_ele;
+	    int least_impact, li_max;
+	    int least_impact_r, least_impact_c;
+	    CELL least_impact_ele;
+
+	    /* initialize least impact */
+	    li_max = n_to_fill + down_uphill + down_downhill;
+	    least_impact = down_uphill + down_downhill;
+	    least_impact_r = first_sink->r;
+	    least_impact_c = first_sink->c;
+	    least_impact_ele = bottom_ele;
+
+	    /* IRA --> */
+
+	    G_debug(1, "impact reduction algorithm");
+
+	    /* start with sink bottom, proceed to spill point
+	     * fill incrementally
+	     * for each step check if IRA condition fulfilled
+	     * proceed until condition no longer met
+	     * then use least impact solution
+	     * the determined new sink bottom can be
+	     * - the original sink bottom: no filling, only carving
+	     * - the spill point: no carving, only filling
+	     * - any cell in between the two */
+
+	    next_r = first_sink->r;
+	    next_c = first_sink->c;
+	    min_bottom_ele = bottom_ele;
+
+	    G_debug(1, "find new fill point");
+
+	    /* include no filling, full carving,
+	     * and full filling, no carving */
+	    while (bottom_ele <= peak_ele) {
+
+		/* get n_to_fill, down_uphill, down_downhill */
+
+		down_uphill = 0;
+		down_downhill = 0;
+
+		/* count cells to fill */
+		next_bottom_ele = peak_ele;
+		n_to_fill = count_fill(next_r, next_c, bottom_ele,
+		                       &n_new_splits, &next_bottom_ele);
+
+		if (n_to_fill < 0)
+		    break;
+
+		/* count channel length from spill point */
+		/* go downstream from spill point
+		 * until we reach bottom ele again */
+		G_debug(2, "count channel length from spill point");
+		r_nbr = peak_r;
+		c_nbr = peak_c;
+		last_ele = ele_nbr = peak_ele;
+		min_bottom_ele = bottom_ele;
+		this_is_flat = 0;
+		while (ele_nbr >= bottom_ele && this_is_flat < 4) {
+		    if (ele_nbr > bottom_ele) {
+			down_downhill++;
+			/* catch min 2 consecutive cells
+			 * in flat area with same ele */
+			if (is_flat(r_nbr, c_nbr, ele_nbr)) {
+			    if (ele_nbr == last_ele) {
+				this_is_flat++;
+				if (this_is_flat > 2 &&
+				    ele_nbr > min_bottom_ele)
+				    min_bottom_ele = bottom_ele + 1;
+			    }
+			    else
+				this_is_flat = 1;
+			}
+			if (next_bottom_ele > ele_nbr)
+			    next_bottom_ele = ele_nbr;
+		    }
+		    bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+
+		    if (drain_val > 0) {
+			r_nbr = r_nbr + asp_r[(int) drain_val];
+			c_nbr = c_nbr + asp_c[(int) drain_val];
+
+			last_ele = ele_nbr;
+			cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+		    }
+		    else {
+			G_debug(2, "reached edge past spill point");
+			break;
+		    }
+		}
+
+		/* carving ok */
+		if (this_is_flat < 4) {
+		    min_bottom_ele = bottom_ele;
+		    /* count cells to carve from sink bottom to spill point */
+		    ele_last = ele_nbr = bottom_ele;
+		    r_nbr = next_r;
+		    c_nbr = next_c;
+		    n_cells = 0;
+		    while (ele_nbr >= ele_last) {
+			n_cells++;
+			if (ele_nbr > bottom_ele) {
+			    down_uphill = n_cells;
+			}
+			bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+
+			if (drain_val > 0) {
+			    r_nbr = r_nbr + asp_r[(int) drain_val];
+			    c_nbr = c_nbr + asp_c[(int) drain_val];
+
+			    ele_last = ele_nbr;
+			    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+			}
+			else {
+			    break;
+			}
+		    }
+		    /* remember least impact */
+		    if (least_impact > n_to_fill + down_uphill +
+			down_downhill) {
+			least_impact = n_to_fill + down_uphill +
+			               down_downhill;
+			least_impact_r = next_r;
+			least_impact_c = next_c;
+			least_impact_ele = bottom_ele;
+		    }
+		}
+		/* carving not ok, need to fill more */
+		else {
+		    G_debug(2, "carving not ok");
+		    least_impact = li_max;
+		    least_impact_r = peak_r;
+		    least_impact_c = peak_c;
+		    least_impact_ele = peak_ele;
+		    min_bottom_ele = bottom_ele + 1;
+		}
+
+		/* there is no better solution by filling more */
+		if (n_to_fill > least_impact)
+		    break;
+
+		G_debug(2,
+			"channel length to spill point %d, channel length from spill point %d, cells to fill %d",
+			down_uphill, down_downhill, n_to_fill);
+
+		/* check IRA condition */
+		/* preference for channel carving, relaxed stream split condition */
+		/* continue filling ? */
+		/* remains a mystery why n_new_splits results in less modifications... */
+		if (sqrt(n_to_fill) < (down_uphill + down_downhill) ||
+		    n_new_splits <= 4 ||
+		    bottom_ele <= min_bottom_ele ||
+		    least_impact == li_max) {
+		    /* continue with IRA */
+		    G_debug(2, "IRA conditions fulfilled");
+		}
+		/* IRA condition no longer fulfilled */
+		else {
+		    G_debug(2, "IRA conditions not met");
+		    G_debug(2, "n to fill: %d", n_to_fill);
+		    G_debug(2, "down_uphill: %d", down_uphill);
+		    G_debug(2, "down_downhill: %d", down_downhill);
+		    break;
+		}
+
+		if (bottom_ele >= peak_ele)
+		    break;
+
+		/* below spill point
+		 * get next higher cell downstream of current bottom */
+		G_debug(2, "get next fill point candidate");
+
+		r_nbr = next_r;
+		c_nbr = next_c;
+		bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+		if (drain_val > 0) {
+
+		    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+		    /* go to next higher cell downstream */
+		    while (ele_nbr == bottom_ele ||
+		           ele_nbr < min_bottom_ele) {
+			bseg_get(&draindir, &drain_val, r_nbr, c_nbr);
+
+			if (drain_val > 0) {
+			    r_nbr = r_nbr + asp_r[(int) drain_val];
+			    c_nbr = c_nbr + asp_c[(int) drain_val];
+
+			    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+			}
+			else {
+			    is_edge = 1;
+			    break;
+			}
+		    }
+		    /* got next downstream cell that's higher than sink bottom */
+		    G_debug(2, "got next downstream cell");
+		}
+		else
+		    is_edge = 1;
+
+		if (is_edge) {
+		    G_debug(1,"IRA reached edge");
+		    break;
+		}
+
+		/* increase ele or go to next point */
+		if (ele_nbr > next_bottom_ele &&
+		    next_bottom_ele >= min_bottom_ele) {
+		    G_debug(2, "increase ele, keep point");
+		    bottom_ele = next_bottom_ele;
+		}
+		else {
+		    next_r = r_nbr;
+		    next_c = c_nbr;
+		    bottom_ele = ele_nbr;
+		}
+	    }
+	    /* <-- IRA */
+	    
+	    if (n_to_fill > -1 && least_impact == li_max)
+		G_warning(_("IRA error"));
+
+	    if (n_to_fill > -1 && (do_all || least_impact <= n_mod_max)) {
+
+		/* (partially) fill the sink */
+		n_to_fill = 0;
+		cseg_get(&ele, &ele_val, first_sink->r, first_sink->c);
+		if (least_impact_ele != ele_val) {
+		    G_debug(1, "IRA sink filling");
+
+		    cseg_get(&ele, &ele_val, least_impact_r,
+		             least_impact_c);
+		    if (ele_val != least_impact_ele) {
+			G_debug(1, "changing ele from %d to %d",
+				ele_val, least_impact_ele);
+			cseg_put(&ele, &least_impact_ele, least_impact_r,
+			         least_impact_c);
+		    }
+		    n_to_fill = fill_sink(least_impact_r, least_impact_c,
+		                          least_impact_ele);
+		    first_sink->r = least_impact_r;
+		    first_sink->c = least_impact_c;
+		    if (least_impact_ele < peak_ele)
+			n_just_a_bit++;
+		    else
+			n_filled++;
+		}
+		else {
+		    n_carved++;
+		    G_debug(1, "IRA at bottom");
+		}
+
+		/* carve if not completely filled */
+		down_downhill = 0;
+		if (least_impact_ele < peak_ele) {
+		    G_debug(2, "IRA carving");
+		    down_downhill = carve(first_sink->r, first_sink->c,
+				          least_impact_ele,
+					  peak_r, peak_c);
+		}
+	    }
+	}
+
+	G_debug(1, "get next sink");
+
+	last_sink = first_sink;
+	first_sink = first_sink->next;
+	G_free(last_sink);
+    }
+
+    G_verbose_message
+	("------------------------------------------------------");
+    G_verbose_message(_("%d sinks processed"), n_sinks);
+    G_verbose_message(_("%d sinks within larger sinks"), n_processed);
+    G_verbose_message(_("%d sinks completely filled"), n_filled);
+    G_verbose_message(_("%d sinks partially filled and carved with IRA"),
+                      n_just_a_bit);
+    G_verbose_message(_("%d channels carved"), n_carved);
+    G_verbose_message
+	("------------------------------------------------------");
+
+    return 1;
+}
+
+int one_cell_extrema(int do_peaks, int do_pits, int all)
+{
+    int r, c, r_nbr, c_nbr;
+    int ct_dir;
+    int skipme;
+    CELL ele_min, ele_max, ele_this, ele_nbr;
+    unsigned int n_pits = 0;
+    unsigned int n_peaks = 0;
+    unsigned int counter = 0;
+    double sumofsquares, mean, stddev, upperci, lowerci;
+    int n_valid;
+
+    G_message(_("Remove one cell extremas"));
+
+    /* not for edges */
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+
+	for (c = 0; c < ncols; c++) {
+
+	    skipme = 0;
+	    cseg_get(&ele, &ele_this, r, c);
+
+	    if (Rast_is_c_null_value(&ele_this))
+		continue;
+
+	    ele_min = INT_MAX;
+	    ele_max = INT_MIN;
+	    sumofsquares = mean = n_valid = 0;
+
+	    /* TODO: better use 5x5 neighbourhood ? */
+	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+		/* get r, c (r_nbr, c_nbr) for neighbours */
+		r_nbr = r + nextdr[ct_dir];
+		c_nbr = c + nextdc[ct_dir];
+		/* check that neighbour is within region */
+		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
+		    c_nbr < ncols) {
+
+		    cseg_get(&ele, &ele_nbr, r_nbr, c_nbr);
+
+		    if (Rast_is_c_null_value(&ele_nbr)) {
+			skipme = 1;
+			break;
+		    }
+		    
+		    n_valid++;
+		    sumofsquares += ele_nbr * ele_nbr;
+		    mean += ele_nbr;
+
+		    if (ele_min > ele_nbr) {
+			ele_min = ele_nbr;
+		    }
+		    if (ele_max < ele_nbr) {
+			ele_max = ele_nbr;
+		    }
+		}
+		else {
+		    skipme = 1;
+		    break;
+		}
+	    }
+
+	    if (skipme)
+		continue;
+
+	    counter++;
+
+	    if (all) {
+		upperci = ele_this - 1;
+		lowerci = ele_this + 1;
+	    }
+	    else {
+		/* remove extremas only if outside 95% CI = mean +- 1.96 * SD */
+		mean /= n_valid;
+		stddev = sqrt(sumofsquares / n_valid - mean * mean);
+		upperci = mean + 1.96 * stddev;
+		lowerci = mean - 1.96 * stddev;
+	    }
+	    
+	    /* one cell pit, lower than all surrounding neighbours */
+	    if (do_pits) {
+		if (ele_this < ele_min && ele_this < lowerci) {
+		    ele_this = ele_min;
+		    cseg_put(&ele, &ele_this, r, c);
+		    n_pits++;
+		}
+	    }
+
+	    /* one cell peak, higher than all surrounding neighbours */
+	    if (do_peaks) {
+		if (ele_this > ele_max && ele_this > upperci) {
+		    ele_this = ele_max;
+		    cseg_put(&ele, &ele_this, r, c);
+		    n_peaks++;
+		}
+	    }
+	}
+    }
+    G_percent(nrows, nrows, 1);	/* finish it */
+
+    G_verbose_message("%u cells checked", counter);
+    G_verbose_message("%u one-cell peaks removed", n_peaks);
+    G_verbose_message("%u one-cell pits removed", n_pits);
+
+    return 1;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/init_search.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/init_search.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/init_search.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,140 @@
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int init_search(int depr_fd)
+{
+    int r, c, r_nbr, c_nbr, ct_dir;
+    void *depr_buf, *depr_ptr;
+    CELL ele_value;
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+    char flag_value, flag_value_nbr, is_null;
+    char asp_value;
+    unsigned int n_depr_cells = 0;
+    unsigned int n_null_cells = nrows * ncols - n_points;
+    int depr_map_type, depr_size;
+
+    nxt_avail_pt = heap_size = 0;
+
+    /* load edge cells and real depressions to A* heap */
+    G_message(_("Set edge points"));
+
+    if (depr_fd > -1) {
+	depr_map_type = Rast_get_map_type(depr_fd);
+	depr_size = Rast_cell_size(depr_map_type);
+	depr_buf = Rast_allocate_buf(depr_map_type);
+    }
+    else {
+	depr_buf = NULL;
+	depr_map_type = 0;
+	depr_size = 0;
+    }
+    depr_ptr = NULL;
+
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+
+	if (depr_fd >= 0) {
+	    Rast_get_row(depr_fd, depr_buf, r, depr_map_type);
+	    depr_ptr = depr_buf;
+	}
+
+	for (c = 0; c < ncols; c++) {
+
+	    bseg_get(&bitflags, &flag_value, r, c);
+	    is_null = FLAG_GET(flag_value, NULLFLAG);
+
+	    if (is_null) {
+		if (depr_fd > -1)
+		    depr_ptr = G_incr_void_ptr(depr_ptr, depr_size);
+		    
+		continue;
+	    }
+
+	    asp_value = 0;
+
+	    if (r == 0 || r == nrows - 1 || c == 0 || c == ncols - 1) {
+
+		if (r == 0 && c == 0)
+		    asp_value = -7;
+		else if (r == 0 && c == ncols - 1)
+		    asp_value = -5;
+		else if (r == nrows - 1 && c == 0)
+		    asp_value = -1;
+		else if (r == nrows - 1 && c == ncols - 1)
+		    asp_value = -3;
+		else if (r == 0)
+		    asp_value = -2;
+		else if (c == 0)
+		    asp_value = -4;
+		else if (r == nrows - 1)
+		    asp_value = -6;
+		else if (c == ncols - 1)
+		    asp_value = -8;
+
+		cseg_get(&ele, &ele_value, r, c);
+		FLAG_SET(flag_value, EDGEFLAG);
+		heap_add(r, c, ele_value, asp_value, flag_value);
+
+		if (depr_fd > -1)
+		    depr_ptr = G_incr_void_ptr(depr_ptr, depr_size);
+
+		continue;
+	    }
+
+	    if (n_null_cells > 0) {
+		/* any neighbour NULL ? */
+		for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+		    /* get r, c (r_nbr, c_nbr) for neighbours */
+		    r_nbr = r + nextdr[ct_dir];
+		    c_nbr = c + nextdc[ct_dir];
+
+		    bseg_get(&bitflags, &flag_value_nbr, r_nbr, c_nbr);
+		    is_null = FLAG_GET(flag_value_nbr, NULLFLAG);
+
+		    if (is_null) {
+			asp_value = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
+			cseg_get(&ele, &ele_value, r, c);
+			FLAG_SET(flag_value, EDGEFLAG);
+			heap_add(r, c, ele_value, asp_value, flag_value);
+
+			break;
+		    }
+		}
+	    }
+
+	    if (asp_value) { /* some neighbour was NULL, point added to list */
+
+		if (depr_fd > -1)
+		    depr_ptr = G_incr_void_ptr(depr_ptr, depr_size);
+
+		continue;
+	    }
+	    
+	    /* real depression ? */
+	    if (depr_fd > -1) {
+		DCELL depr_val = Rast_get_d_value(depr_ptr, depr_map_type);
+
+		if (!Rast_is_null_value(depr_ptr, depr_map_type) && depr_val != 0) {
+		    cseg_get(&ele, &ele_value, r, c);
+		    FLAG_SET(flag_value, DEPRFLAG);
+		    heap_add(r, c, ele_value, asp_value, flag_value);
+		    n_depr_cells++;
+		}
+		depr_ptr = G_incr_void_ptr(depr_ptr, depr_size);
+	    }
+	}
+    }
+    G_percent(nrows, nrows, 2);	/* finish it */
+
+    if (depr_fd > -1) {
+	G_free(depr_buf);
+    }
+
+    G_debug(1, "%d edge cells", heap_size - n_depr_cells);
+    if (n_depr_cells)
+	G_debug(1, "%d cells in depressions", n_depr_cells);
+
+    return 1;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/load.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/load.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/load.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,97 @@
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int ele_round(double x)
+{
+    return (x > 0.0 ? x + .5 : x - .5);
+}
+
+/*
+ * loads elevation map to segment file and gets start points for A* Search,
+ * start points are edges
+ */
+int load_map(int ele_fd)
+{
+    int r, c;
+    char flag_value, asp_value = 0;
+    void *ele_buf, *ptr;
+    CELL ele_value;
+    DCELL dvalue;
+    int ele_size;
+    int ele_map_type;
+
+    G_message(_("Load elevation map"));
+
+    n_search_points = n_points = 0;
+
+    ele_map_type = Rast_get_map_type(ele_fd);
+    ele_size = Rast_cell_size(ele_map_type);
+    ele_buf = Rast_allocate_buf(ele_map_type);
+
+    if (ele_buf == NULL) {
+	G_warning(_("Could not allocate memory"));
+	return -1;
+    }
+
+    ele_scale = 1;
+    if (ele_map_type == FCELL_TYPE || ele_map_type == DCELL_TYPE)
+	ele_scale = 1000;	/* should be enough to do the trick */
+
+    G_debug(1, "start loading %d rows, %d cols", nrows, ncols);
+    for (r = 0; r < nrows; r++) {
+
+	G_percent(r, nrows, 2);
+
+	Rast_get_row(ele_fd, ele_buf, r, ele_map_type);
+	ptr = ele_buf;
+
+	for (c = 0; c < ncols; c++) {
+
+	    flag_value = 0;
+
+	    /* check for masked and NULL cells */
+	    if (Rast_is_null_value(ptr, ele_map_type)) {
+		FLAG_SET(flag_value, NULLFLAG);
+		FLAG_SET(flag_value, INLISTFLAG);
+		FLAG_SET(flag_value, WORKEDFLAG);
+		FLAG_SET(flag_value, WORKED2FLAG);
+		Rast_set_c_null_value(&ele_value, 1);
+	    }
+	    else {
+		switch (ele_map_type) {
+		case CELL_TYPE:
+		    ele_value = *((CELL *) ptr);
+		    break;
+		case FCELL_TYPE:
+		    dvalue = *((FCELL *) ptr);
+		    dvalue *= ele_scale;
+		    ele_value = ele_round(dvalue);
+		    break;
+		case DCELL_TYPE:
+		    dvalue = *((DCELL *) ptr);
+		    dvalue *= ele_scale;
+		    ele_value = ele_round(dvalue);
+		    break;
+		}
+
+		n_points++;
+	    }
+
+	    cseg_put(&ele, &ele_value, r, c);
+	    bseg_put(&draindir, &asp_value, r, c);
+	    bseg_put(&bitflags, &flag_value, r, c);
+
+	    ptr = G_incr_void_ptr(ptr, ele_size);
+	}
+    }
+    G_percent(nrows, nrows, 1);	/* finish it */
+
+    Rast_close(ele_fd);
+    G_free(ele_buf);
+
+    G_debug(1, "%d non-NULL cells", n_points);
+
+    return 1;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,89 @@
+
+#ifndef __LOCAL_PROTO_H__
+#define __LOCAL_PROTO_H__
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include "seg.h"
+#include "flag.h"
+
+#define INDEX(r, c) ((r) * ncols + (c))
+#define MAXDEPTH 1000     /* maximum supported tree depth of stream network */
+
+struct ddir
+{
+    int pos;
+    int dir;
+};
+
+struct point
+{
+    int r, c;
+};
+
+struct heap_point {
+   unsigned int added;
+   CELL ele;
+   int r, c;
+};
+
+struct sink_list
+{
+    int r, c;
+    struct sink_list *next;
+};
+
+struct snode
+{
+    int r, c;
+    int id;
+    int n_trib;           /* number of tributaries */
+    int n_trib_total;     /* number of all upstream stream segments */
+    int n_alloc;          /* n allocated tributaries */
+    int *trib;
+    double *acc;
+};
+
+extern struct snode *stream_node;
+extern int nrows, ncols;
+extern unsigned int n_search_points, n_points, nxt_avail_pt;
+extern unsigned int heap_size;
+extern unsigned int n_sinks;
+extern int n_mod_max, size_max;
+extern int do_all, keep_nat, nat_thresh;
+extern unsigned int n_stream_nodes, n_alloc_nodes;
+extern struct point *outlets;
+extern struct sink_list *sinks, *first_sink;
+extern unsigned int n_outlets, n_alloc_outlets;
+extern char drain[3][3];
+extern unsigned int first_cum;
+extern char sides;
+extern int c_fac;
+extern int ele_scale;
+extern struct RB_TREE *draintree;
+
+extern SSEG search_heap;
+extern SSEG astar_pts;
+extern BSEG bitflags;
+extern CSEG ele;
+extern BSEG draindir;
+extern CSEG stream;
+
+/* load.c */
+int load_map(int);
+
+/* init_search.c */
+int init_search(int);
+
+/* do_astar.c */
+int do_astar(void);
+unsigned int heap_add(int, int, CELL, char, char);
+
+/* hydro_con.c */
+int hydro_con(void);
+int one_cell_extrema(int, int, int);
+
+/* close.c */
+int close_map(char *, int);
+
+#endif /* __LOCAL_PROTO_H__ */

Added: grass-addons/grass7/grass7/raster/r.hydrodem/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,348 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.hydrodem
+ * AUTHOR(S):    Markus Metz <markus.metz.giswork gmail.com>
+ * PURPOSE:      Hydrological analysis
+ *               DEM hydrological conditioning based on A* Search
+ * COPYRIGHT:    (C) 1999-2009 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+struct snode *stream_node;
+int nrows, ncols;
+unsigned int n_search_points, n_points, nxt_avail_pt;
+unsigned int heap_size;
+unsigned int n_sinks;
+int n_mod_max, size_max;
+int do_all, keep_nat, nat_thresh;
+unsigned int n_stream_nodes, n_alloc_nodes;
+struct point *outlets;
+struct sink_list *sinks, *first_sink;
+unsigned int n_outlets, n_alloc_outlets;
+
+char drain[3][3] = { {7, 6, 5}, {8, 0, 4}, {1, 2, 3} };
+
+unsigned int first_cum;
+char sides;
+int c_fac;
+int ele_scale;
+struct RB_TREE *draintree;
+
+SSEG search_heap;
+BSEG bitflags;
+CSEG ele;
+BSEG draindir;
+CSEG stream;
+
+
+int main(int argc, char *argv[])
+{
+    struct
+    {
+	struct Option *ele, *depr, *memory;
+    } input;
+    struct
+    {
+	struct Option *ele_hydro;
+	struct Option *mod_max;
+	struct Option *size_max;
+	struct Flag *do_all;
+    } output;
+    struct GModule *module;
+    int ele_fd, ele_map_type, depr_fd;
+    int memory;
+    int seg_cols, seg_rows;
+    double seg2kb;
+    int num_open_segs, num_open_array_segs, num_seg_total;
+    double memory_divisor, heap_mem, disk_space;
+    const char *mapset;
+    struct Colors colors;
+
+    G_gisinit(argv[0]);
+
+    /* Set description */
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("hydrology"));
+    module->description = _("Hydrological conditioning, sink removal");
+
+    input.ele = G_define_standard_option(G_OPT_R_INPUT);
+    input.ele->key = "input";
+    input.ele->label = _("Elevation map");
+    input.ele->description =
+	_("Elevation map to be hydrologically corrected");
+
+    input.depr = G_define_standard_option(G_OPT_R_INPUT);
+    input.depr->key = "depression";
+    input.depr->required = NO;
+    input.depr->label = _("Depression map");
+    input.depr->description =
+	_("Map indicating real depressions that must not be modified");
+
+    input.memory = G_define_option();
+    input.memory->key = "memory";
+    input.memory->type = TYPE_INTEGER;
+    input.memory->required = NO;
+    input.memory->answer = "300";
+    input.memory->description = _("Maximum memory to be used in MB");
+
+    output.ele_hydro = G_define_standard_option(G_OPT_R_OUTPUT);
+    output.ele_hydro->key = "output";
+    output.ele_hydro->description =
+	_("Name of hydrologically conditioned raster map");
+    output.ele_hydro->required = YES;
+
+    output.mod_max = G_define_option();
+    output.mod_max->key = "mod";
+    output.mod_max->description =
+	(_("Only remove sinks requiring not more than <mod> cell modifications."));
+    output.mod_max->type = TYPE_INTEGER;
+    output.mod_max->answer = "4";
+    output.mod_max->required = YES;
+
+    output.size_max = G_define_option();
+    output.size_max->key = "size";
+    output.size_max->description =
+	(_("Only remove sinks not larger than <size> cells."));
+    output.size_max->type = TYPE_INTEGER;
+    output.size_max->answer = "4";
+    output.size_max->required = YES;
+
+    output.do_all = G_define_flag();
+    output.do_all->key = 'a';
+    output.do_all->label = (_("Remove all sinks."));
+    output.do_all->description =
+	(_("By default only minor corrections are done to the DEM and "
+	  "the result will not be 100% hydrologically correct."
+	  "Use this flag to override default."));
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    /***********************/
+    /*    check options    */
+    /***********************/
+
+    /* input maps exist ? */
+    if (!G_find_raster(input.ele->answer, ""))
+	G_fatal_error(_("Raster map <%s> not found"), input.ele->answer);
+	
+    if (input.depr->answer) {
+	if (!G_find_raster(input.depr->answer, ""))
+	    G_fatal_error(_("Raster map <%s> not found"),
+	                  input.depr->answer);
+    }
+
+    if ((n_mod_max = atoi(output.mod_max->answer)) <= 0)
+	G_fatal_error(_("'%s' must be a positive integer"),
+	              output.mod_max->key);
+
+    if ((size_max = atoi(output.size_max->answer)) <= 0)
+	G_fatal_error(_("'%s' must be a positive integer"),
+		      output.size_max->key);
+
+    if (input.memory->answer) {
+	memory = atoi(input.memory->answer);
+	if (memory <= 0)
+	    G_fatal_error(_("Memory must be positive but is %d"),
+			  memory);
+    }
+    else
+	memory = 300;
+
+    do_all = output.do_all->answer;
+
+    if (!do_all) {
+	G_verbose_message(_("All sinks with max %d cells to be modified will be removed"),
+			  n_mod_max);
+	G_verbose_message(_("All sinks not larger than %d cells will be removed."),
+			  size_max);
+    }
+
+    /*********************/
+    /*    preparation    */
+    /*********************/
+
+    /* open input maps */
+    mapset = G_find_raster2(input.ele->answer, "");
+    ele_fd = Rast_open_old(input.ele->answer, mapset);
+    if (ele_fd < 0)
+	G_fatal_error(_("Could not open input map %s"), input.ele->answer);
+
+    if (input.depr->answer) {
+	mapset = G_find_raster2(input.depr->answer, "");
+	depr_fd = Rast_open_old(input.depr->answer, mapset);
+	if (depr_fd < 0)
+	    G_fatal_error(_("Could not open input map %s"),
+	                  input.depr->answer);
+    }
+    else
+	depr_fd = -1;
+
+    /* set global variables */
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    sides = 8;			/* not a user option */
+
+    ele_map_type = Rast_get_map_type(ele_fd);
+
+    /* segment structures */
+    seg_rows = seg_cols = 64;
+    seg2kb = seg_rows * seg_cols / 1024.;
+    
+    /* balance segment files */
+    /* elevation: * 2 */
+    memory_divisor = seg2kb * sizeof(CELL) * 2;
+    /* drainage direction: as is */
+    memory_divisor += seg2kb * sizeof(char);
+    /* flags: * 4 */
+    memory_divisor += seg2kb * sizeof(char) * 4;
+    /* heap points: / 4 */
+    memory_divisor += seg2kb * sizeof(struct heap_point) / 4.;
+    
+    /* KB -> MB */
+    memory_divisor /= 1024.;
+
+    num_open_segs = memory / memory_divisor;
+    /* heap_mem is in MB */
+    heap_mem = num_open_segs * seg2kb * sizeof(struct heap_point) /
+               (4. * 1024.);
+    num_seg_total = (ncols / seg_cols + 1) * (nrows / seg_rows + 1);
+    if (num_open_segs > num_seg_total) {
+	heap_mem += (num_open_segs - num_seg_total) * memory_divisor;
+	heap_mem -= (num_open_segs - num_seg_total) * seg2kb *
+	            sizeof(struct heap_point) / (4. * 1024.);
+	num_open_segs = num_seg_total;
+    }
+    if (num_open_segs < 16) {
+	num_open_segs = 16;
+	heap_mem = num_open_segs * seg2kb * sizeof(struct heap_point) /
+	           (4. * 1024.);
+    }
+    disk_space = (1. * sizeof(CELL) + 2 * sizeof(char) +
+                 sizeof(struct heap_point));
+    disk_space *= (num_seg_total * seg2kb / 1024.);  /* KB -> MB */
+    
+    G_verbose_message(_("%.2f of data are kept in memory"),
+                      100. * num_open_segs / num_seg_total);
+    G_verbose_message(_("Will need up to %.2f MB of disk space"), disk_space);
+
+    /* open segment files */
+    G_verbose_message(_("Create temporary files..."));
+    cseg_open(&ele, seg_rows, seg_cols, num_open_segs * 2);
+    if (num_open_segs * 2 > num_seg_total)
+	heap_mem += (num_open_segs * 2 - num_seg_total) * seg2kb * sizeof(CELL) / 1024.;
+    bseg_open(&draindir, seg_rows, seg_cols, num_open_segs);
+    bseg_open(&bitflags, seg_rows, seg_cols, num_open_segs * 4);
+    if (num_open_segs * 4 > num_seg_total)
+	heap_mem += (num_open_segs * 4 - num_seg_total) * seg2kb / 1024.;
+
+    /* load map */
+    if (load_map(ele_fd) < 0) {
+	cseg_close(&ele);
+	bseg_close(&draindir);
+	bseg_close(&bitflags);
+	G_fatal_error(_("Could not load input map"));
+    }
+    
+    if (n_points == 0) {
+	cseg_close(&ele);
+	bseg_close(&draindir);
+	bseg_close(&bitflags);
+	G_fatal_error(_("No non-NULL cells loaded from input map"));
+    }
+
+    /* one-based d-ary search_heap */
+    G_debug(1, "open segments for A* search heap");
+	
+    /* allowed memory for search heap in MB */
+    G_debug(1, "heap memory %.2f MB", heap_mem);
+    /* columns per segment */
+    /* larger is faster */
+    seg_cols = seg_rows * seg_rows * seg_rows;
+    num_seg_total = n_points / seg_cols;
+    if (n_points % seg_cols > 0)
+	num_seg_total++;
+    /* no need to have more segments open than exist */
+    num_open_array_segs = (1 << 20) * heap_mem / 
+                           (seg_cols * sizeof(struct heap_point));
+    if (num_open_array_segs > num_seg_total)
+	num_open_array_segs = num_seg_total;
+    if (num_open_array_segs < 2)
+	num_open_array_segs = 2;
+
+    G_debug(1, "A* search heap open segments %d, total %d",
+            num_open_array_segs, num_seg_total);
+    G_debug(1, "segment size for heap points: %d", seg_cols);
+    /* the search heap will not hold more than 5% of all points at any given time ? */
+    /* chances are good that the heap will fit into one large segment */
+    seg_open(&search_heap, 1, n_points + 1, 1, seg_cols,
+	     num_open_array_segs, sizeof(struct heap_point), 1);
+
+    /********************/
+    /*    processing    */
+    /********************/
+
+    /* remove one cell extrema */
+    one_cell_extrema(1, 1, 0);
+
+    /* initialize A* search */
+    if (init_search(depr_fd) < 0) {
+	seg_close(&search_heap);
+	cseg_close(&ele);
+	bseg_close(&draindir);
+	bseg_close(&bitflags);
+	G_fatal_error(_("Could not initialize search"));
+    }
+
+    if (depr_fd >= 0) {
+	Rast_close(depr_fd);
+    }
+
+    /* sort elevation and get initial stream direction */
+    if (do_astar() < 0) {
+	seg_close(&search_heap);
+	cseg_close(&ele);
+	bseg_close(&draindir);
+	bseg_close(&bitflags);
+	G_fatal_error(_("Could not sort elevation map"));
+    }
+    seg_close(&search_heap);
+
+    /* hydrological corrections */
+    if (hydro_con() < 0) {
+	cseg_close(&ele);
+	bseg_close(&draindir);
+	bseg_close(&bitflags);
+	G_fatal_error(_("Could not apply hydrological conditioning"));
+    }
+
+    /* write output maps */
+    if (close_map(output.ele_hydro->answer, ele_map_type) < 0) {
+	cseg_close(&ele);
+	bseg_close(&draindir);
+	bseg_close(&bitflags);
+	G_fatal_error(_("Could not write output map"));
+    }
+
+    cseg_close(&ele);
+    bseg_close(&draindir);
+    bseg_close(&bitflags);
+
+    Rast_read_colors(input.ele->answer, mapset, &colors);
+    Rast_write_colors(output.ele_hydro->answer, G_mapset(), &colors);
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/r.hydrodem.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/r.hydrodem.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/r.hydrodem.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,84 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.hydrodem</em> applies hydrological conditioning (sink removal) to 
+a required input <em>elevation</em> map. If the conditioned elevation 
+map is going to be used as input elevation for <em>r.watershed</em>, 
+only small sinks should be removed and the amount of modifications 
+restricted with the <b>mod</b> option. For other modules such as 
+<em>r.terraflow</em> or third-party software, full sink removal is 
+recommended.
+
+<h2>OPTIONS</h2>
+
+<dl>
+<dt><b>input</b> 
+
+<dd>Input map, required: Digital elevation model to be corrected. Gaps
+in the elevation map that are located within the area of interest should
+be filled beforehand, e.g. with <em>r.fillnulls</em> or 
+<em>r.resamp.bspline</em>, to avoid distortions.
+<p>
+<dt><b>output</b>
+<dd>Output map, required: Hydrologically conditioned digital elevation
+model. By default, only minor modifications are done and not all sinks 
+are removed.
+<p>
+<dt><b>size</b>
+<dd>All sinks of up to <b>size</b> cells will be removed.
+Default is 4, if in doubt, decrease and not increase.
+<p>
+<dt><b>mod</b>
+<dd>All sinks will be removed that require not more than <b>mod</b> 
+cells to be modifed. Often, rather large sinks can be removed by 
+carving through only few cells. Default is 4, if in doubt, increase
+and not decrease.
+<p>
+<dt><b>-a</b>
+<dd><b>Not recommended if input for <em>r.watershed</em> is generated.</b>
+<br>
+With the <b>-a</b> flag set, all sinks will be removed using an impact 
+reduction approach based on Lindsay & Creed (2005). The output will be a 
+depression-less digital elevation model, suitable for e.g.
+<em>r.terraflow</em> or other hydrological analyses that require a 
+depression-less DEM as input.
+</dl>
+
+<h2>NOTES</h2>
+
+This module is designed for <em>r.watershed</em> with the purpose to
+slightly denoise a DEM prior to analysis. First, all one-cell peaks and
+pits are removed, then the actual hydrological corrections are applied.
+In most cases, the removal of one-cell extrema could already be
+sufficient to improve <em>r.watershed</em> results in difficult terrain,
+particularly nearly flat areas.
+<p>
+The impact reduction algorithm used by <em>r.hydrodem</em> is based on 
+Lindsay & Creed (2005), with some additional checks for 
+hydrological consistency. With complete sink removal, results of 
+<em>r.terraflow</em> are very similar to results of <em>r.watershed</em>.
+<p>
+<em>r.hydrodem</em> uses the same method to determine drainage directions 
+like <em>r.watershed</em>.
+<p>
+
+<h2>REFERENCES</h2>
+Lindsay, J. B., and Creed, I. F. 2005. Removal of artifact depressions 
+from digital elevation models: towards a minimum impact approach. 
+Hydrological Processes 19, 3113-3126. 
+DOI: <a href=http://dx.doi.org/10.1002/hyp.5835>10.1002/hyp.5835</a>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.watershed.html">r.watershed</a>,
+<a href="r.terraflow.html">r.terraflow</a>,
+<a href="r.fill.dir.html">r.fill.dir</a>, 
+<a href="r.fillnulls.html">r.fillnulls</a>, 
+<a href="r.resamp.bspline.html">r.resamp.bspline</a>
+</em>
+
+<h2>AUTHOR</h2>
+Markus Metz
+
+<p><i>Last changed: $Date: 2012-01-09 18:41:56 +0100 (Mon, 09 Jan 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.hydrodem/seg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/seg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/seg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,112 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int
+seg_open(SSEG *sseg, int nrows, int ncols, int row_in_seg, int col_in_seg,
+	 int nsegs_in_memory, int size_struct, int fill)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    sseg->filename = NULL;
+    sseg->fd = -1;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("seg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (fill)
+	errflag = segment_format(fd, nrows, ncols, row_in_seg,
+	                         col_in_seg, size_struct);
+    else
+	errflag = segment_format_nofill(fd, nrows, ncols, row_in_seg,
+	                         col_in_seg, size_struct);
+
+    if (0 > errflag) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("seg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("seg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("seg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(sseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("seg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("seg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    sseg->filename = filename;
+    sseg->fd = fd;
+    return 0;
+}
+
+int seg_close(SSEG *sseg)
+{
+    segment_release(&(sseg->seg));
+    close(sseg->fd);
+    unlink(sseg->filename);
+    return 0;
+}
+
+int seg_put(SSEG *sseg, char *value, int row, int col)
+{
+    if (segment_put(&(sseg->seg), value, row, col) < 0) {
+	G_warning(_("seg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_put_row(SSEG *sseg, char *value, int row)
+{
+    if (segment_put_row(&(sseg->seg), value, row) < 0) {
+	G_warning(_("seg_put_row(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_get(SSEG *sseg, char *value, int row, int col)
+{
+    if (segment_get(&(sseg->seg), value, row, col) < 0) {
+	G_warning(_("seg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_get_row(SSEG *sseg, char *value, int row)
+{
+    if (segment_get_row(&(sseg->seg), value, row) < 0) {
+	G_warning(_("seg_get_row(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_flush(SSEG *sseg)
+{
+    segment_flush(&(sseg->seg));
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.hydrodem/seg.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.hydrodem/seg.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.hydrodem/seg.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,78 @@
+#ifndef __SEG_H__
+#define __SEG_H__
+
+#include <grass/raster.h>
+#include <grass/segment.h>
+
+#define CSEG struct _c_s_e_g_
+CSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+    char *name;			/* raster map read into segment file */
+    char *mapset;
+};
+
+#define DSEG struct _d_s_e_g_
+DSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+    char *name;			/* raster map read into segment file */
+    char *mapset;
+};
+
+#define BSEG struct _b_s_e_g_
+BSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+    char *name;			/* raster map read into segment file */
+    char *mapset;
+};
+
+#define SSEG struct _s_s_e_g_
+SSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+};
+
+/* bseg.c */
+int bseg_close(BSEG *);
+int bseg_get(BSEG *, char *, int, int);
+int bseg_open(BSEG *, int, int, int);
+int bseg_put(BSEG *, char *, int, int);
+int bseg_put_row(BSEG *, char *, int);
+int bseg_read_raster(BSEG *, char *, char *);
+int bseg_write_raster(BSEG *, char *);
+
+/* cseg.c */
+int cseg_close(CSEG *);
+int cseg_get(CSEG *, CELL *, int, int);
+int cseg_open(CSEG *, int, int, int);
+int cseg_put(CSEG *, CELL *, int, int);
+int cseg_put_row(CSEG *, CELL *, int);
+int cseg_read_raster(CSEG *, char *, char *);
+int cseg_write_raster(CSEG *, char *);
+
+/* dseg.c */
+int dseg_close(DSEG *);
+int dseg_get(DSEG *, double *, int, int);
+int dseg_open(DSEG *, int, int, int);
+int dseg_put(DSEG *, double *, int, int);
+int dseg_put_row(DSEG *, double *, int);
+int dseg_read_raster(DSEG *, char *, char *);
+int dseg_write_raster(DSEG *, char *);
+
+/* seg.c */
+int seg_close(SSEG *);
+int seg_get(SSEG *, char *, int, int);
+int seg_open(SSEG *, int, int, int, int, int, int, int);
+int seg_put(SSEG *, char *, int, int);
+int seg_put_row(SSEG *, char *, int);
+int seg_get(SSEG *, char *, int, int);
+int seg_get_row(SSEG *, char *, int);
+int seg_flush(SSEG *);
+
+#endif /* __SEG_H__ */

Added: grass-addons/grass7/grass7/raster/r.in.srtm.region/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.srtm.region/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.srtm.region/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.in.srtm.region
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script

Added: grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,36 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.in.srtm.region</em> imports all SRTM V2.1 tiles covering the 
+current region or region extents given with <b>region</b> into GRASS, 
+patches the tiles together and optionally interpolates holes.
+<p>
+<em>r.in.srtm.region</em> downloads SRTM tiles from:<br>
+<a href="http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/">http://dds.cr.usgs.gov/srtm/</a>
+<br>
+or optionally uses a local folder with previously downloaded files if 
+the <b>local</b> option is given.
+
+<h2>NOTES</h2>
+
+<em>r.in.srtm.region</em> imports only SRTM tiles with 3 arcsec resolution.
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.in.srtm.html">r.in.srtm</a>
+</em>
+<p>The <a href="http://www2.jpl.nasa.gov/srtm/">Shuttle Radar Topography Mission</a>
+homepage at NASA's JPL.
+<br>
+The <a href="http://pub7.bravenet.com/forum/537683448/">SRTM Web Forum</a>
+
+<h2>REFERENCES</h2>
+
+M. Neteler, 2005. <a href="http://grass.osgeo.org/newsletter/GRASSNews_vol3.pdf">SRTM and VMAP0 data in OGR and GRASS.</a> <i><a href="http://grass.osgeo.org/newsletter/">GRASS Newsletter</a></i>, Vol.3, pp. 2-6, June 2005. ISSN 1614-8746.
+
+
+<h2>AUTHORS</h2>
+
+Markus Metz<br>
+
+<p><i>Last changed: $Date: 2012-01-07 12:33:11 +0100 (Sat, 07 Jan 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,347 @@
+#!/usr/bin/env python
+
+############################################################################
+#
+# MODULE:       r.in.srtm.region
+#
+# AUTHOR(S):    Markus Metz
+#
+# PURPOSE:      Create a DEM from 3 arcsec SRTM v2.1 tiles
+#
+# COPYRIGHT:    (C) 2011 GRASS development team
+#
+#               This program is free software under the GNU General
+#               Public License (>=v2). Read the file COPYING that
+#               comes with GRASS for details.
+#
+#############################################################################
+
+#%module
+#% description: Creates a DEM from 3 arcsec SRTM v2.1 tiles.
+#% keywords: raster
+#% keywords: import
+#%end
+#%option G_OPT_R_OUTPUT
+#% description: Name for output raster map
+#% required: yes
+#%end
+#%option
+#% key: url
+#% description: base url to fetch SRTM v2.1 tiles
+#% answer: http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/
+#% required: no
+#%end
+#%option G_OPT_M_DIR
+#% key: local
+#% label: local folder with SRTM v2.1 tiles
+#% description: use local folder instead of url to retrieve SRTM tiles
+#% required: no
+#%end
+#%option
+#% key: region
+#% type: double
+#% label: Import subregion only (default is current region)
+#% description: Format: xmin,ymin,xmax,ymax - usually W,S,E,N
+#% key_desc: xmin,ymin,xmax,ymax
+#% multiple: yes
+#% required: no
+#%end
+#%option
+#% key: memory
+#% type: integer
+#% description: Memory in MB for interpolation
+#% answer: 300
+#% required: no
+#%end
+#%flag
+#%  key: n
+#%  description: Fill null cells
+#%end
+
+
+proj = ''.join([
+    'GEOGCS[',
+    '"wgs84",',
+    'DATUM["WGS_1984",SPHEROID["wgs84",6378137,298.257223563],TOWGS84[0.000000,0.000000,0.000000]],',
+    'PRIMEM["Greenwich",0],',
+    'UNIT["degree",0.0174532925199433]',
+    ']'])
+
+import sys
+import os
+import shutil
+import atexit
+import urllib
+import urllib2
+import time
+
+import grass.script as grass
+
+def import_local_tile(tile, local, pid):
+    output = tile + '.r.in.srtm2.tmp.' + str(pid)
+    local_tile = str(tile) + '.hgt.zip'
+    
+    path = os.path.join(local, local_tile)
+    if os.path.exists(path):
+	path = os.path.join(local, tile)
+	grass.run_command('r.in.srtm', input = path, output = output, quiet = True)
+	return 1
+
+    # SRTM subdirs: Africa, Australia, Eurasia, Islands, North_America, South_America
+    for srtmdir in ('Africa', 'Australia', 'Eurasia', 'Islands', 'North_America', 'South_America'):
+	path = os.path.join(local, srtmdir, local_tile)
+
+	if os.path.exists(path):
+	    path = os.path.join(local, srtmdir, tile)
+	    grass.run_command('r.in.srtm', input = path, output = output, quiet = True)
+	    return 1
+
+    return 0
+
+def download_tile(tile, url, pid):
+    output = tile + '.r.in.srtm2.tmp.' + str(pid)
+    local_tile = str(tile) + '.hgt.zip'
+
+    urllib.urlcleanup()
+
+    # SRTM subdirs: Africa, Australia, Eurasia, Islands, North_America, South_America
+    for srtmdir in ('Africa', 'Australia', 'Eurasia', 'Islands', 'North_America', 'South_America'):
+	remote_tile = str(url) + str(srtmdir) + '/' + local_tile
+	goturl = 1
+    
+	try:
+	    f = urllib2.urlopen(remote_tile)
+	    fo = open(local_tile, 'w+b')
+	    fo.write(f.read())
+	    fo.close
+	    time.sleep(0.5)
+	    # does not work:
+	    #urllib.urlretrieve(remote_tile, local_tile, data = None)
+	except:
+	    goturl = 0
+	    pass
+	
+	if goturl == 1:
+	    return 1
+
+    return 0
+    
+    
+def cleanup():
+    if not in_temp:
+	return
+    os.chdir(currdir)
+    grass.run_command('g.region', region = tmpregionname)
+    grass.run_command('g.remove', region = tmpregionname, quiet = True)
+    #grass.try_rmdir(tmpdir)
+
+def main():
+    global tile, tmpdir, in_temp, currdir, tmpregionname
+
+    in_temp = False
+
+    url = options['url']
+    local = options['local']
+    output = options['output']
+    memory = options['memory']
+    fillnulls = flags['n']
+    
+    if len(url) == 0 and len(local) == 0:
+	grass.fatal(_("Either 'url' or 'local' is needed"))
+	
+    if len(local) == 0:
+	local = None
+
+    # are we in LatLong location?
+    s = grass.read_command("g.proj", flags='j')
+    kv = grass.parse_key_val(s)
+    if kv['+proj'] != 'longlat':
+	grass.fatal(_("This module only operates in LatLong locations"))
+
+    if fillnulls == 1 and memory <= 0:
+	grass.warning(_("Amount of memory to use for interpolation must be positive, setting to 300 MB"))
+	memory = '300'
+
+    # make a temporary directory
+    tmpdir = grass.tempfile()
+    grass.try_remove(tmpdir)
+    os.mkdir(tmpdir)
+    currdir = os.getcwd()
+    pid = os.getpid()
+
+    # change to temporary directory
+    os.chdir(tmpdir)
+    in_temp = True
+    if local is None:
+	local = tmpdir
+
+    # get extents
+    reg = grass.region()
+    tmpregionname = 'r_in_srtm2_tmp_region'
+    grass.run_command('g.region', save = tmpregionname)
+    if options['region'] is None or options['region'] == '':
+	north = reg['n']
+	south = reg['s']
+	east = reg['e']
+	west = reg['w']
+    else:
+	west, south, east, north = options['region'].split(',')
+	west = float(west)
+	south = float(south)
+	east = float(east)
+	north = float(north)
+
+    # adjust extents to cover SRTM tiles: 1 degree bounds
+    tmpint = int(north)
+    if tmpint < north:
+	north = tmpint + 1
+    else:
+	north = tmpint
+    tmpint = int(south)
+    if tmpint > south:
+	south = tmpint - 1
+    else:
+	south = tmpint
+    tmpint = int(east)
+    if tmpint < east:
+	east = tmpint + 1
+    else:
+	east = tmpint
+    tmpint = int(west)
+    if tmpint > west:
+	west = tmpint - 1
+    else:
+	west = tmpint
+	
+    rows = abs(north - south)
+    cols = abs(east - west)
+    ntiles = rows * cols
+    grass.message(_("Importing %d SRTM tiles...") % ntiles, flag = 'i')
+    counter = 1
+
+    srtmtiles = ''
+    valid_tiles = 0
+    for ndeg in range(south, north):
+	for edeg in range(west, east):
+	    grass.percent(counter, ntiles, 1)
+	    counter += 1
+	    if ndeg < 0:
+		tile = 'S'
+	    else:
+		tile = 'N'
+	    tile = tile + '%02d' % abs(ndeg)
+	    if edeg < 0:
+		tile = tile + 'W'
+	    else:
+		tile = tile + 'E'
+	    tile = tile + '%03d' % abs(edeg)
+	    grass.debug("Tile: %s" % tile, debug = 1)
+	    
+	    if local != tmpdir:
+		gotit = import_local_tile(tile, local, pid)
+	    else:
+		gotit = download_tile(tile, url, pid)
+		if gotit == 1:
+		    gotit = import_local_tile(tile, tmpdir, pid)
+	    if gotit == 1:
+		grass.verbose(_("Tile %s successfully imported") % tile)
+		valid_tiles += 1
+	    else:
+		# create tile with zeros
+		# north
+		if ndeg < 0:
+		    tmpn = '%02d:59:58.5S' % (abs(ndeg) - 2)
+		else:
+		    tmpn = '%02d:00:01.5N' % (ndeg + 1)
+		# south
+		if ndeg <= 0:
+		    tmps = '%02d:00:01.5S' % abs(ndeg)
+		else:
+		    tmps = '%02d:59:58.5N' % (ndeg - 1)
+		# east
+		if edeg < 0:
+		    tmpe = '%03d:59:58.5W' % (abs(edeg) - 2)
+		else:
+		    tmpe = '%03d:00:01.5E' % (edeg + 1)
+		# west
+		if edeg <= 0:
+		    tmpw = '%03d:00:01.5W' % abs(edeg)
+		else:
+		    tmpw = '%03d:59:58.5E' % (edeg - 1)
+
+		grass.run_command('g.region', n = tmpn, s = tmps, e = tmpe, w = tmpw, res = '00:00:03')
+		grass.run_command('r.mapcalc', expression = "%s = 0" % (tile + '.r.in.srtm2.tmp.' + str(pid)), quiet = True)
+		grass.run_command('g.region', region = tmpregionname)
+
+
+    # g.mlist with fs = comma does not work ???
+    srtmtiles = grass.read_command('g.mlist',
+                                   type = 'rast',
+				   pattern = '*.r.in.srtm2.tmp.%d' % pid,
+				   fs = 'newline',
+				   quiet = True)
+
+    srtmtiles = srtmtiles.splitlines()
+    srtmtiles = ','.join(srtmtiles)
+
+    if valid_tiles == 0:
+	grass.run_command('g.remove', rast = str(srtmtiles), quiet = True)
+	grass.warning(_("No tiles imported"))
+	if local != tmpdir:
+	    grass.fatal(_("Please check if local folder <%s> is correct.") % local)
+	else:
+	    grass.fatal(_("Please check internet connection and if url <%s> is correct.") % url)
+
+    grass.run_command('g.region', rast = str(srtmtiles));
+    
+    if fillnulls == 0:
+	grass.run_command('r.patch', input = srtmtiles, output = output)
+    else:
+	ncells = grass.region()['cells'] 
+	if long(ncells) > 1000000000:
+	    grass.message(_("%s cells to interpolate, this will take some time") % str(ncells), flag = 'i')
+	grass.run_command('r.patch', input = srtmtiles, output = output + '.holes')
+	mapstats = grass.parse_command('r.univar', map = output + '.holes', flags = 'g', quiet = True)
+	if mapstats['null_cells'] == '0':
+	    grass.run_command('g.rename', rast = '%s,%s' % (output + '.holes', output), quiet = True)
+	else:
+	    grass.run_command('r.resamp.bspline',
+			      input = output + '.holes',
+			      output = output + '.interp',
+			      se = '0.0025', sn = '0.0025',
+			      method = 'bilinear',
+			      memory = memory,
+			      flags = 'n')
+	    grass.run_command('r.patch',
+	                      input = '%s,%s' % (output + '.holes',
+			      output + '.interp'),
+			      output = output + '.float',
+			      flags = 'z')
+	    grass.run_command('r.mapcalc', expression = '%s = round(%s)' % (output, output + '.float'))
+	    grass.run_command('g.remove',
+			      rast = '%s,%s,%s' % (output + '.holes', output + '.interp', output + '.float'),
+			      quiet = True)
+
+    grass.run_command('g.remove', rast = str(srtmtiles), quiet = True)
+
+    # nice color table
+    grass.run_command('r.colors', map = output, color = 'srtm', quiet = True)
+
+    # write metadata:
+    tmphist = grass.tempfile()
+    f = open(tmphist, 'w+')
+    f.write(os.environ['CMDLINE'])
+    f.close()
+    grass.run_command('r.support', map = output,
+		      loadhistory = tmphist,
+		      description = 'generated by r.in.srtm.region',
+		      source1 = 'SRTM V2.1',
+		      source2 = (local if local != tmpdir else url))
+    grass.try_remove(tmphist)
+
+    grass.message(_("Done: generated map <%s>") % output)
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    atexit.register(cleanup)
+    main()


Property changes on: grass-addons/grass7/grass7/raster/r.in.srtm.region/r.in.srtm.region.py
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.in.wms2/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.wms2/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.wms2/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,18 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.in.wms2
+
+MODULES = wms_base wms_drv wms_gdal_drv
+PYFILES := $(patsubst %,$(ETC)/%.py,$(MODULES))
+PYCFILES := $(patsubst %,$(ETC)/%.pyc,$(MODULES))
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+
+default: script $(PYFILES) $(PYCFILES)
+
+$(ETCDIR):
+	$(MKDIR) $@
+
+$(ETC)/%: % | $(ETC)
+	$(INSTALL_DATA) $< $@

Added: grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,81 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.in.wms2</em> handles all of downloading and importing raster
+data from an <a href="http://www.opengeospatial.org/standards/wms">OGC
+WMS</a> and <a href="http://www.opengeospatial.org/standards/wmts">OGC
+WMTS</a> web mapping servers. It need only be told the desired data to
+collect (bounds and resolution) via a region, the server to get the
+data from, and the layer or layers to get. It downloads the data in
+tiles, reprojects it, imports it, and patches it back together.
+
+<h2>NOTES</h2>
+
+<!--
+By default data is downloaded to <tt>$GISDBASE/wms_download</tt>. This can be changed
+by setting the <b>folder</b> option when using <em>r.in.wms</em>.
+-->
+
+<p>To understand the data you are getting it is necessary to look at the
+capabilities of the WMS server. This should be available via a capabilities
+request. This is an
+<a href="http://wms.jpl.nasa.gov/wms.cgi?request=GetCapabilities">example
+capabilities request to NASA's OnEarth server</a>.
+
+<h2>EXAMPLES</h2>
+
+<h3>General Get Capabilities Request</h3>
+
+<div class="code"><pre>
+r.in.wms2 -c url=http://wms.cuzk.cz/wms.asp
+</pre></div>
+
+<h3>>Download raster data from WMS server (GetMap request)</h3>
+
+
+World extend data:
+
+<div class="code"><pre>
+r.in.wms2 url=http://iceds.ge.ucl.ac.uk/cgi-bin/icedswms layers=bluemarble,landsat_1_01 styles=default,default output=landsat srs=4326 format=png 
+</pre></div>
+* Server supports only WMS 1.1.1 <br>
+
+<div class="code"><pre>
+r.in.wms2 url=http://132.156.97.59/cgi-bin/worldmin_en-ca_ows layers=GSC:WORLD_PrecambrianDomains output=pokus srs=4326 format=jpeg 
+</pre></div>
+* Server supports only WMS 1.1.1 
+<br>
+<br>
+
+<div class="code"><pre>
+r.in.wms2 url=http://gpp3-wxs.ign.fr/yourAPIkey/geoportail/wmts layers=ORTHOIMAGERY.ORTHOPHOTOS output=orthophoto srs=3857 format=jpeg driver=WMTS_GRASS style=normal password=* username=*
+</pre></div>
+* Username, password and API key can be get at <a href="http://api.ign.fr/">IGN API</a> website
+<br>
+<br>
+
+Data in extend of Czech Republic:
+
+<div class="code"><pre>
+r.in.wms2 output=kn url=http://wms.cuzk.cz/wms.asp layers=prehledka_kraju-linie srs=4326 format=png
+</pre></div>
+
+<div class="code"><pre>
+r.in.wms2 url=http://geoportal.cuzk.cz/WMTS_ORTOFOTO/WMTService.aspx layers=orto output=ortofoto srs=3857 format=jpeg driver=WMTS_GRASS style=default
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em>
+  <a href="r.in.gdal.html">r.in.gdal</a>,
+  <a href="r.patch.html">r.patch</a>,
+  <a href="r.colors.html">r.colors</a>,
+  <a href="r.composite.html">r.composite</a>,
+  <a href="v.in.wfs.html">v.in.wfs</a>
+</em>
+
+<h2>AUTHORS</h2>
+
+Stepan Turek, Czech Technical University in Prague, Czech Republic (bachelor's final project 2012, mentor: Martin Landa) 
+
+<p>
+<i>Last changed: $Date: 2012-10-10 00:02:55 +0200 (Wed, 10 Oct 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+"""
+MODULE:    r.in.wms2
+
+AUTHOR(S): Stepan Turek <stepan.turek AT seznam.cz>
+
+PURPOSE:   Downloads and imports data from WMS server.
+
+COPYRIGHT: (C) 2012 Stepan Turek, and by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+"""
+
+#%module
+#% description: Downloads and imports data from WMS servers.
+#% keywords: raster
+#% keywords: import
+#% keywords: wms
+#%end
+
+#%option
+#% key: url
+#% type: string
+#% description:URL of WMS server 
+#% required: yes
+#%end
+
+#%option
+#% key: layers
+#% type: string
+#% description: Layers to request from map server
+#% multiple: yes
+#% required: yes
+#%end
+
+#%option G_OPT_R_OUTPUT
+#% description: Name for output raster map
+#%end
+
+#%option
+#% key: srs
+#% type: integer
+#% description: EPSG number of source projection for request 
+#% answer:4326 
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: region
+#% type: string
+#% description: Named region to request data for. Current region used if omitted
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: wms_version
+#% type:string
+#% description:WMS standard
+#% options:1.1.1,1.3.0
+#% answer:1.1.1
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: format
+#% type: string
+#% description: Image format requested from the server
+#% options: geotiff,tiff,jpeg,gif,png
+#% answer: geotiff
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: method
+#% type: string
+#% description: Reprojection method to use
+#% options:near,bilinear,cubic,cubicspline
+#% answer:near
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: maxcols
+#% type:integer
+#% description: Maximum columns to request at a time
+#% answer:400
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: maxrows
+#% type: integer
+#% description: Maximum rows to request at a time
+#% answer: 300
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: urlparams
+#% type:string
+#% description: Additional query parameters for server
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: username
+#% type:string
+#% description: Username for server connection
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: password
+#% type:string
+#% description: Password for server connection
+#% guisection: Request properties
+#%end
+
+#%option
+#% key: styles
+#% type: string
+#% description: Styles to request from map server
+#% multiple: yes
+#% guisection: Map style
+#%end
+
+#%option
+#% key: bgcolor
+#% type: string
+#% description: Color of map background
+#% guisection: Map style
+#%end
+
+#%flag
+#% key: o
+#% description: Don't request transparent data
+#% guisection: Map style
+#%end
+
+#%flag
+#% key: c
+#% description: Get capabilities
+#% guisection: Request properties
+#% suppress_required: yes
+#%end
+
+#%option
+#% key: driver
+#% type:string
+#% description: Driver for communication with server
+#% options:WMS_GDAL, WMS_GRASS, WMTS_GRASS
+#% answer:WMS_GDAL
+#%end
+
+
+import os
+import sys
+sys.path.insert(1, os.path.join(os.path.dirname(sys.path[0]), 'etc', 'r.in.wms2'))
+
+import grass.script as grass
+
+def main():
+    if 'GRASS' in options['driver']:
+        grass.debug("Using GRASS driver")
+        from wms_drv import WMSDrv
+        wms = WMSDrv()
+    elif 'GDAL' in options['driver']:
+        grass.debug("Using GDAL WMS driver")
+        from wms_gdal_drv import WMSGdalDrv
+        wms = WMSGdalDrv()
+    
+    if flags['c']:
+        wms.GetCapabilities(options)
+    else:
+        wms.GetMap(options, flags)  
+    
+    return 0
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())


Property changes on: grass-addons/grass7/grass7/raster/r.in.wms2/r.in.wms2.py
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.in.wms2/wms_base.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.wms2/wms_base.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.wms2/wms_base.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,400 @@
+import os
+from   math import ceil
+
+from urllib2 import urlopen, HTTPError, URLError
+from httplib import HTTPException
+
+import grass.script as grass
+
+class WMSBase:
+    def __init__(self):
+        # these variables are information for destructor
+        self.temp_files_to_cleanup = []
+        self.cleanup_mask   = False
+        self.cleanup_layers = False
+        
+        self.params = {}
+        self.tile_size = {'bbox' : None}
+
+        self.temp_map = None
+        
+    def __del__(self):
+        # removes temporary mask, used for import transparent or warped temp_map
+        if self.cleanup_mask:
+            # clear temporary mask, which was set by module      
+            if grass.run_command('r.mask',
+                                 quiet = True,
+                                 flags = 'r') != 0:  
+                grass.fatal(_('%s failed') % 'r.mask')
+            
+            # restore original mask, if exists 
+            if grass.find_file(self.params['output'] + self.original_mask_suffix, element = 'cell', mapset = '.' )['name']:
+                if grass.run_command('g.copy',
+                                     quiet = True,
+                                     rast =  self.params['output'] + self.original_mask_suffix + ',MASK') != 0:
+                    grass.fatal(_('%s failed') % 'g.copy')
+        
+        # tries to remove temporary files, all files should be
+        # removed before, implemented just in case of unexpected
+        # stop of module
+        for temp_file in self.temp_files_to_cleanup:
+            grass.try_remove(temp_file)
+        
+        # remove temporary created rasters
+        if self.cleanup_layers: 
+            maps = []
+            for suffix in ('.red', '.green', '.blue', '.alpha', self.original_mask_suffix):
+                rast = self.params['output'] + suffix
+                if grass.find_file(rast, element = 'cell', mapset = '.')['file']:
+                    maps.append(rast)
+            
+            if maps:
+                grass.run_command('g.remove',
+                                  quiet = True,
+                                  flags = 'f',
+                                  rast  = ','.join(maps))
+        
+        # deletes environmental variable which overrides region 
+        if 'GRASS_REGION' in os.environ.keys():
+            os.environ.pop('GRASS_REGION')
+        
+    def _debug(self, fn, msg):
+        grass.debug("%s.%s: %s" %
+                    (self.__class__.__name__, fn, msg))
+        
+    def _initializeParameters(self, options, flags):
+        self._debug("_initialize_parameters", "started")
+        
+        # initialization of module parameters (options, flags)
+
+        self.params['driver'] = options['driver']
+
+        self.flags = flags
+
+        if self.flags['o'] and 'WMS' not in self.params['driver']:
+            grass.warning(_("Flag '%s' is relevant only for WMS.") % 'o')
+        elif self.flags['o']:
+            self.params['transparent'] = 'FALSE'
+        else:
+            self.params['transparent'] = 'TRUE'   
+
+        for key in ['url', 'layers', 'styles', 'output', 'method']:
+            self.params[key] = options[key].strip()
+
+        for key in ['password', 'username', 'urlparams']:
+            self.params[key] = options[key] 
+            if self.params[key] != "" and 'GRASS' not in self.params['driver']:
+                grass.warning(_("Parameter '%s' is relevant only for %s drivers.") % (key, '*_GRASS'))
+        
+        self.params['bgcolor'] = options['bgcolor'].strip()
+        if self.params['bgcolor'] != "" and 'WMS_GRASS' not in self.params['driver']:
+            grass.warning(_("Parameter '%s' is relevant only for %s driver.") % ('bgcolor', 'WMS_GRASS'))
+                
+        self.params['wms_version'] = options['wms_version']        
+        if self.params['wms_version'] == "1.3.0":
+            self.params['proj_name'] = "CRS"
+        else:
+            self.params['proj_name'] = "SRS" 
+        
+        if  options['format'] == "geotiff":
+            self.params['format'] = "image/geotiff"
+        elif options['format'] == "tiff":
+            self.params['format'] = "image/tiff"
+        elif options['format'] == "png":
+            self.params['format'] = "image/png"
+        elif  options['format'] == "jpeg":
+            self.params['format'] = "image/jpeg"
+            if flags['o']:
+                grass.warning(_("JPEG format does not support transparency"))
+        elif self.params['format'] == "gif":
+            self.params['format'] = "image/gif"
+        else:
+            self.params['format'] = self.params['format']
+        
+        self.params['srs'] = int(options['srs'])
+        if self.params['srs'] <= 0:
+            grass.fatal(_("Invalid EPSG code %d") % self.params['srs'])
+        
+        # read projection info
+        self.proj_location = grass.read_command('g.proj', 
+                                                flags ='jf').rstrip('\n')
+
+        if self.params['srs'] in [3857, 900913]:
+            # HACK: epsg 3857 def: http://spatialreference.org/ref/sr-org/7483/
+            # g.proj can return: ...+a=6378137 +rf=298.257223563... (WGS84 elipsoid def instead of sphere), it can make 20km shift in Y, when raster is transformed
+            # needed to be tested on more servers
+            self.proj_srs = '+proj=merc +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +no_defs +a=6378137 +b=6378137 +nadgrids=@null +to_meter=1 +wktext'
+        else:
+            self.proj_srs = grass.read_command('g.proj', 
+                                               flags = 'jf', 
+                                               epsg = str(self.params['srs']) ).rstrip('\n')
+
+        if not self.proj_srs or not self.proj_location:
+            grass.fatal(_("Unable to get projection info"))
+        
+        # set region 
+        self.params['region'] = options['region']
+        if self.params['region']:                 
+            if not grass.find_file(name = self.params['region'], element = 'windows', mapset = '.' )['name']:
+                grass.fatal(_("Region <%s> not found") % self.params['region'])
+        
+        if self.params['region']:
+            s = grass.read_command('g.region',
+                                   quiet = True,
+                                   flags = 'ug',
+                                   region = self.params['region'])
+            self.region = grass.parse_key_val(s, val_type = float)
+        else:
+            self.region = grass.region()
+        
+        min_tile_size = 100
+        maxcols = int(options['maxcols'])
+        if maxcols <= min_tile_size:
+            grass.fatal(_("Maxcols must be greater than 100"))
+        
+        maxrows = int(options['maxrows'])
+        if maxrows <= min_tile_size:
+            grass.fatal(_("Maxrows must be greater than 100"))
+        
+        # setting optimal tile size according to maxcols and maxrows constraint and region cols and rows      
+        self.tile_size['cols'] = int(self.region['cols'] / ceil(self.region['cols'] / float(maxcols)))
+        self.tile_size['rows'] = int(self.region['rows'] / ceil(self.region['rows'] / float(maxrows)))
+        
+        # suffix for existing mask (during overriding will be saved
+        # into raster named:self.params['output'] + this suffix)
+        self.original_mask_suffix = "_temp_MASK"
+        
+        # check names of temporary rasters, which module may create 
+        maps = []
+        for suffix in ('.red', '.green', '.blue', '.alpha', self.original_mask_suffix ):
+            rast = self.params['output'] + suffix
+            if grass.find_file(rast, element = 'cell', mapset = '.')['file']:
+                maps.append(rast)
+        
+        if len(maps) != 0:
+            grass.fatal(_("Please change output name, or change names of these rasters: %s, "
+                          "module needs to create this temporary maps during runing") % ",".join(maps))
+        
+        # default format for GDAL library
+        self.gdal_drv_format = "GTiff"
+        
+        self._debug("_initialize_parameters", "finished")
+
+    def GetMap(self, options, flags):
+        """!Download data from WMS server and import data
+        (using GDAL library) into GRASS as a raster map."""
+
+        self._initializeParameters(options, flags)  
+
+        self.bbox     = self._computeBbox()
+        
+        self.temp_map = self._download()
+
+        if not self.temp_map:
+            return
+
+        self._createOutputMap() 
+    
+    def _fetchCapabilities(self, options): 
+        """!Download capabilities from WMS server
+        """
+        # download capabilities file
+        cap_url = options['url']
+
+        if 'WMTS' in options['driver']:
+            cap_url += "?SERVICE=WMTS&REQUEST=GetCapabilities&VERSION=1.0.0"
+        else:
+            cap_url += "?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=" + options['wms_version'] 
+
+        try:
+            cap = urlopen(cap_url)
+        except (IOError, HTTPError):
+            grass.fatal(_("Unable to get capabilities from '%s'") % options['url'])
+        
+        return cap
+
+    def GetCapabilities(self, options): 
+        """!Get capabilities from WMS server
+        """
+        cap  = self._fetchCapabilities(options)
+        cap_lines = cap.readlines()
+        for line in cap_lines: 
+            print line 
+        
+    def _computeBbox(self):
+        """!Get region extent for WMS query (bbox)
+        """
+        self._debug("_computeBbox", "started")
+        
+        bbox_region_items = {'maxy' : 'n', 'miny' : 's', 'maxx' : 'e', 'minx' : 'w'}  
+        bbox = {}
+
+        if self.proj_srs == self.proj_location: # TODO: do it better
+            for bbox_item, region_item in bbox_region_items.iteritems():
+                bbox[bbox_item] = self.region[region_item]
+        
+        # if location projection and wms query projection are
+        # different, corner points of region are transformed into wms
+        # projection and then bbox is created from extreme coordinates
+        # of the transformed points
+        else:
+            for bbox_item, region_item  in bbox_region_items.iteritems():
+                bbox[bbox_item] = None
+
+            temp_region = self._tempfile()
+            
+            try:
+                temp_region_opened = open(temp_region, 'w')
+                temp_region_opened.write("%f %f\n%f %f\n%f %f\n%f %f\n"  %\
+                                       (self.region['e'], self.region['n'],\
+                                        self.region['w'], self.region['n'],\
+                                        self.region['w'], self.region['s'],\
+                                        self.region['e'], self.region['s'] ))
+            except IOError:
+                 grass.fatal(_("Unable to write data into tempfile"))
+            finally:           
+                temp_region_opened.close()            
+
+            points = grass.read_command('m.proj', flags = 'd',
+                                        proj_output = self.proj_srs,
+                                        proj_input = self.proj_location,
+                                        input = temp_region) # TODO: stdin
+            grass.try_remove(temp_region)
+            if not points:
+                grass.fatal(_("Unable to determine region, %s failed") % 'm.proj')
+            
+            points = points.splitlines()
+            if len(points) != 4:
+                grass.fatal(_("Region definition: 4 points required"))
+            
+            for point in points:
+                try:
+                    point = map(float, point.split("|"))
+                except ValueError:
+                    grass.fatal(_('Reprojection of region using m.proj failed.'))
+                if not bbox['maxy']:
+                    bbox['maxy'] = point[1]
+                    bbox['miny'] = point[1]
+                    bbox['maxx'] = point[0]
+                    bbox['minx'] = point[0]
+                    continue
+                
+                if   bbox['maxy'] < point[1]:
+                    bbox['maxy'] = point[1]
+                elif bbox['miny'] > point[1]:
+                    bbox['miny'] = point[1]
+                
+                if   bbox['maxx'] < point[0]:
+                    bbox['maxx'] = point[0]
+                elif bbox['minx'] > point[0]:
+                    bbox['minx'] = point[0]  
+        
+        self._debug("_computeBbox", "finished -> %s" % bbox)
+
+        # Ordering of coordinates axis of geographic coordinate
+        # systems in WMS 1.3.0 is flipped. If  self.tile_size['flip_coords'] is 
+        # True, coords in bbox need to be flipped in WMS query.
+
+        return bbox
+
+    def _createOutputMap(self): 
+        """!Import downloaded data into GRASS, reproject data if needed
+        using gdalwarp
+        """
+        # reprojection of raster
+        if self.proj_srs != self.proj_location: # TODO: do it better
+            grass.message(_("Reprojecting raster..."))
+            temp_warpmap = self._tempfile()
+            
+            if int(os.getenv('GRASS_VERBOSE', '2')) <= 2:
+                nuldev = file(os.devnull, 'w+')
+            else:
+                nuldev = None
+            
+            #"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"
+            # RGB rasters - alpha layer is added for cropping edges of projected raster
+            if self.temp_map_bands_num == 3:
+                ps = grass.Popen(['gdalwarp',
+                                  '-s_srs', '%s' % self.proj_srs,
+                                  '-t_srs', '%s' % self.proj_location,
+                                  '-r', self.params['method'], '-dstalpha',
+                                  self.temp_map, temp_warpmap], stdout = nuldev)
+            # RGBA rasters
+            else:
+                ps = grass.Popen(['gdalwarp',
+                                  '-s_srs', '%s' % self.proj_srs,
+                                  '-t_srs', '%s' % self.proj_location,
+                                  '-r', self.params['method'],
+                                  self.temp_map, temp_warpmap], stdout = nuldev)
+            ps.wait()
+            
+            if nuldev:
+                nuldev.close()
+            
+            if ps.returncode != 0:
+                grass.fatal(_('%s failed') % 'gdalwarp')
+        # raster projection is same as projection of location
+        else:
+            temp_warpmap = self.temp_map
+        
+        grass.message(_("Importing raster map into GRASS..."))
+        # importing temp_map into GRASS
+        if grass.run_command('r.in.gdal',
+                             quiet = True,
+                             input = temp_warpmap,
+                             output = self.params['output']) != 0:
+            grass.fatal(_('%s failed') % 'r.in.gdal')
+        
+        # information for destructor to cleanup temp_layers, created
+        # with r.in.gdal
+        self.cleanup_layers = True
+        
+        # setting region for full extend of imported raster
+        os.environ['GRASS_REGION'] = grass.region_env(rast = self.params['output'] + '.red')
+        
+        # mask created from alpha layer, which describes real extend
+        # of warped layer (may not be a rectangle), also mask contains
+        # transparent parts of raster
+        if grass.find_file( self.params['output'] + '.alpha', element = 'cell', mapset = '.' )['name']:
+            # saving current mask (if exists) into temp raster
+            if grass.find_file('MASK', element = 'cell', mapset = '.' )['name']:
+                if grass.run_command('g.copy',
+                                     quiet = True,
+                                     rast = 'MASK,' + self.params['output'] + self.original_mask_suffix) != 0:    
+                    grass.fatal(_('%s failed') % 'g.copy')
+            
+            # info for destructor
+            self.cleanup_mask = True
+            if grass.run_command('r.mask',
+                                 quiet = True,
+                                 overwrite = True,
+                                 maskcats = "0",
+                                 flags = 'i',
+                                 input = self.params['output'] + '.alpha') != 0: 
+                grass.fatal(_('%s failed') % 'r.mask')
+        
+        if grass.run_command('r.composite',
+                             quiet = True,
+                             red = self.params['output'] + '.red',
+                             green = self.params['output'] +  '.green',
+                             blue = self.params['output'] + '.blue',
+                             output = self.params['output'] ) != 0:
+                grass.fatal(_('%s failed') % 'r.composite')
+        
+        grass.try_remove(temp_warpmap)
+        grass.try_remove(self.temp_map) 
+
+    def _tempfile(self):
+        """!Create temp_file and append list self.temp_files_to_cleanup 
+            with path of file 
+     
+        @return string path to temp_file
+        """
+        temp_file = grass.tempfile()
+        if temp_file is None:
+            grass.fatal(_("Unable to create temporary files"))
+        
+        # list of created tempfiles for destructor
+        self.temp_files_to_cleanup.append(temp_file)
+        
+        return temp_file

Added: grass-addons/grass7/grass7/raster/r.in.wms2/wms_drv.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.wms2/wms_drv.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.wms2/wms_drv.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,603 @@
+
+import grass.script as grass 
+from urllib2 import urlopen, HTTPError
+from httplib import HTTPException
+
+try:
+    from osgeo import gdal
+    from osgeo import gdalconst 
+except:
+    grass.fatal(_("Unable to load GDAL python bindings"))
+
+import urllib2
+import xml.etree.ElementTree as etree
+
+import numpy as Numeric
+Numeric.arrayrange = Numeric.arange
+
+from math import pi, floor
+from wms_base import WMSBase
+
+class WMSDrv(WMSBase):
+    def _download(self):
+        """!Downloads data from WMS server using own driver
+        
+        @return temp_map with downloaded data
+        """ 
+        grass.message(_("Downloading data from WMS server..."))
+
+        # initialize correct manager according to chosen OGC service
+        if self.params['driver'] == 'WMTS_GRASS':
+            req_mgr = WMTSRequestMgr(self.params, self.bbox, self.region, self.proj_srs, self._fetchCapabilities(self.params))
+        elif self.params['driver'] == 'WMS_GRASS':
+            req_mgr = WMSRequestMgr(self.params, self.bbox, self.region, self.tile_size, self.proj_srs)
+
+        # set password and username to urlib2
+        if self.params['username']:
+            passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
+            passman.add_password(None, self.params['url'], self.params['username'], self.params['password'])
+            auth_handler = urllib2.HTTPBasicAuthHandler(passman)
+            opener = urllib2.build_opener(auth_handler)
+            urllib2.install_opener(opener)
+
+        # get information about size in pixels and bounding box of raster, where all tiles will be joined
+        map_region = req_mgr.GetMapRegion()
+
+        init = True
+        temp_map = None
+
+        # iterate through all tiles and download them
+        while True:
+
+            # get url for request the tile and information for placing the tile into raster with other tiles
+            tile = req_mgr.GetNextTile()
+
+            # if last tile has been already downloaded 
+            if not tile:
+                break
+
+            # url for request the tile
+            query_url = tile[0]
+
+            # the tile size and offset in pixels for placing it into raster where tiles are joined
+            tileRef = tile[1]
+
+            grass.debug(query_url)
+            try: 
+                wms_data = urllib2.urlopen(query_url)
+            except (IOError, HTTPException), e:
+                if HTTPError == type(e) and e.code == 401:
+                    grass.fatal(_("Authorization failed"))           
+                else:
+                    grass.fatal(_("Unable to fetch data from server")) 
+
+            temp_tile = self._tempfile()
+                
+            # download data into temporary file
+            try:
+                temp_tile_opened = open(temp_tile, 'w')
+                temp_tile_opened.write(wms_data.read())
+            except IOError:
+                grass.fatal(_("Unable to write data into tempfile"))
+            finally:
+                temp_tile_opened.close()
+                
+            tile_dataset_info = gdal.Open(temp_tile, gdal.GA_ReadOnly) 
+            if tile_dataset_info is None:
+                # print error xml returned from server
+                try:
+                    error_xml_opened = open(temp_tile, 'r')
+                    err_str = error_xml_opened.read()     
+                except IOError:
+                    grass.fatal(_("Unable to read data from tempfile"))
+                finally:
+                    error_xml_opened.close()
+
+                if  err_str is not None:
+                    grass.fatal(_("WMS server error: %s") %  err_str)
+                else:
+                    grass.fatal(_("WMS server unknown error") )
+                
+            band = tile_dataset_info.GetRasterBand(1) 
+            cell_type_func = band.__swig_getmethods__["DataType"]#??
+            bands_number_func = tile_dataset_info.__swig_getmethods__["RasterCount"]
+                
+            temp_tile_pct2rgb = None
+            if bands_number_func(tile_dataset_info) == 1 and band.GetRasterColorTable() is not None:
+                # expansion of color table into bands 
+                temp_tile_pct2rgb = self._tempfile()
+                tile_dataset = self._pct2rgb(temp_tile, temp_tile_pct2rgb)
+            else: 
+                tile_dataset = tile_dataset_info
+                
+            # initialization of temp_map_dataset, where all tiles are merged
+            if init:
+                temp_map = self._tempfile()
+                    
+                driver = gdal.GetDriverByName(self.gdal_drv_format)
+                metadata = driver.GetMetadata()
+                if not metadata.has_key(gdal.DCAP_CREATE) or \
+                       metadata[gdal.DCAP_CREATE] == 'NO':
+                    grass.fatal(_('Driver %s does not supports Create() method') % drv_format)  
+                    
+                self.temp_map_bands_num = bands_number_func(tile_dataset)
+                temp_map_dataset = driver.Create(temp_map, map_region['cols'], map_region['rows'],
+                                                 self.temp_map_bands_num, cell_type_func(band))
+                init = False
+                
+            # tile is written into temp_map
+            tile_to_temp_map = tile_dataset.ReadRaster(0, 0, tileRef['sizeX'], tileRef['sizeY'],
+                                                             tileRef['sizeX'], tileRef['sizeY'])
+                
+            temp_map_dataset.WriteRaster(tileRef['t_cols_offset'], tileRef['t_rows_offset'],
+                                         tileRef['sizeX'],  tileRef['sizeY'], tile_to_temp_map) 
+                
+            tile_dataset = None
+            tile_dataset_info = None
+            grass.try_remove(temp_tile)
+            grass.try_remove(temp_tile_pct2rgb)    
+        
+        if not temp_map:
+            return temp_map
+        # georeferencing and setting projection of temp_map
+        projection = grass.read_command('g.proj', 
+                                        flags = 'wf',
+                                        epsg =self.params['srs']).rstrip('\n')
+        temp_map_dataset.SetProjection(projection)
+
+        pixel_x_length = (map_region['maxx'] - map_region['minx']) / int(map_region['cols'])
+        pixel_y_length = (map_region['miny'] - map_region['maxy']) / int(map_region['rows'])
+
+        geo_transform = [map_region['minx'] , pixel_x_length  , 0.0 , map_region['maxy'] , 0.0 , pixel_y_length] 
+        temp_map_dataset.SetGeoTransform(geo_transform )
+        temp_map_dataset = None
+        
+        return temp_map
+    
+    def _pct2rgb(self, src_filename, dst_filename):
+        """!Create new dataset with data in dst_filename with bands according to src_filename 
+        raster color table - modified code from gdal utility pct2rgb
+        
+        @return new dataset
+        """  
+        out_bands = 4
+        band_number = 1
+        
+        # open source file
+        src_ds = gdal.Open(src_filename)
+        if src_ds is None:
+            grass.fatal(_('Unable to open %s ' % src_filename))
+            
+        src_band = src_ds.GetRasterBand(band_number)
+        
+        # Build color table
+        lookup = [ Numeric.arrayrange(256), 
+                   Numeric.arrayrange(256), 
+                   Numeric.arrayrange(256), 
+                   Numeric.ones(256)*255 ]
+        
+        ct = src_band.GetRasterColorTable()	
+        if ct is not None:
+            for i in range(min(256,ct.GetCount())):
+                entry = ct.GetColorEntry(i)
+                for c in range(4):
+                    lookup[c][i] = entry[c]
+        
+        # create the working file
+        gtiff_driver = gdal.GetDriverByName(self.gdal_drv_format)
+        tif_ds = gtiff_driver.Create(dst_filename,
+                                     src_ds.RasterXSize, src_ds.RasterYSize, out_bands)
+        
+        # do the processing one scanline at a time
+        for iY in range(src_ds.RasterYSize):
+            src_data = src_band.ReadAsArray(0,iY,src_ds.RasterXSize,1)
+            
+            for iBand in range(out_bands):
+                band_lookup = lookup[iBand]
+                
+                dst_data = Numeric.take(band_lookup,src_data)
+                tif_ds.GetRasterBand(iBand+1).WriteArray(dst_data,0,iY)
+        
+        return tif_ds       
+
+class BaseRequestMgr:
+    """!Base class for request managers. 
+    """
+    def _isGeoProj(self, proj):
+        """!Is it geographic projection? 
+        """       
+        if (proj.find("+proj=latlong")  != -1 or \
+            proj.find("+proj=longlat")  != -1):
+
+            return True
+        return False
+
+    def find(self, etreeElement, tag, ns = None):
+        """!Wraper for etree element find method. 
+        """
+        if not ns:
+            res = etreeElement.find(tag)
+        else:
+            res = etreeElement.find(ns(tag))
+
+        if res is None:
+            grass.fatal(_("Unable to parse capabilities file. \n Tag '%s' was not found.") % tag)
+
+        return res
+
+    def findall(self, etreeElement, tag, ns = None):
+        """!Wraper for etree element findall method. 
+        """
+        if not ns:
+            res = etreeElement.findall(tag)
+        else:
+            res = etreeElement.findall(ns(tag))
+
+        if not res:
+            grass.fatal(_("Unable to parse capabilities file. \n Tag '%s' was not found.") % tag)
+
+        return res
+
+class WMSRequestMgr(BaseRequestMgr):
+    def __init__(self, params, bbox, region, tile_size, proj_srs, cap_file = None):
+        """!Initialize data needed for iteration through tiles.
+        """
+        self.version = params['wms_version']
+        proj = params['proj_name'] + "=EPSG:"+ str(params['srs'])
+        self.url = params['url'] + ("?SERVICE=WMS&REQUEST=GetMap&VERSION=%s&LAYERS=%s&WIDTH=%s&HEIGHT=%s&STYLES=%s&BGCOLOR=%s&TRANSPARENT=%s" % \
+                  (params['wms_version'], params['layers'], tile_size['cols'], tile_size['rows'], params['styles'], \
+                   params['bgcolor'], params['transparent']))
+        self.url += "&" +proj+ "&" + "FORMAT=" + params['format']
+        
+        self.bbox = bbox
+        self.proj_srs = proj_srs
+        self.tile_rows = tile_size['rows']
+        self.tile_cols = tile_size['cols']
+
+        if params['urlparams'] != "":
+            self.url += "&" + params['urlparams']
+        
+        cols = int(region['cols'])
+        rows = int(region['rows'])
+        
+        # computes parameters of tiles 
+        self.num_tiles_x = cols / self.tile_cols 
+        self.last_tile_x_size = cols % self.tile_cols
+        self.tile_length_x =  float(self.tile_cols) / float(cols) * (self.bbox['maxx'] - self.bbox['minx']) 
+        
+        self.last_tile_x = False
+        if self.last_tile_x_size != 0:
+            self.last_tile_x = True
+            self.num_tiles_x = self.num_tiles_x + 1
+        
+        self.num_tiles_y = rows / self.tile_rows 
+        self.last_tile_y_size = rows % self.tile_rows
+        self.tile_length_y =  float(self.tile_rows) / float(rows) * (self.bbox['maxy'] - self.bbox['miny']) 
+        
+        self.last_tile_y = False
+        if self.last_tile_y_size != 0:
+            self.last_tile_y = True
+            self.num_tiles_y = self.num_tiles_y + 1
+        
+        self.tile_bbox = dict(self.bbox)
+        self.tile_bbox['maxx'] = self.bbox['minx']  + self.tile_length_x
+
+        self.i_x = 0 
+        self.i_y = 0
+
+        self.map_region = self.bbox
+        self.map_region['cols'] = cols
+        self.map_region['rows'] = rows
+
+    def GetMapRegion(self):
+        """!Get size in pixels and bounding box of raster where all tiles will be merged.
+        """
+        return self.map_region
+
+    def GetNextTile(self):
+        """!Get url for request the tile from server and information for merging the tile with other tiles
+        """
+
+        tileRef = {}
+
+        if self.i_x >= self.num_tiles_x:
+            return None
+            
+        tileRef['sizeX'] = self.tile_cols
+        if self.i_x == self.num_tiles_x - 1 and self.last_tile_x:
+            tileRef['sizeX'] = self.last_tile_x_size
+         
+        # set bbox for tile (N, S)
+        if self.i_y != 0:
+            self.tile_bbox['miny'] -= self.tile_length_y 
+            self.tile_bbox['maxy'] -= self.tile_length_y
+        else:
+            self.tile_bbox['maxy'] = self.bbox['maxy']
+            self.tile_bbox['miny'] = self.bbox['maxy'] - self.tile_length_y
+
+        tileRef['sizeY'] = self.tile_rows
+        if self.i_y == self.num_tiles_y - 1 and self.last_tile_y:
+            tileRef['sizeY'] = self.last_tile_y_size 
+
+        if self._isGeoProj(self.proj_srs) and self.version == "1.3.0":                
+            query_bbox = self._flipBbox(self.tile_bbox, self.proj_srs)
+        else:
+            query_bbox = self.tile_bbox
+        query_url = self.url + "&" + "BBOX=%s,%s,%s,%s" % ( query_bbox['minx'],  query_bbox['miny'],  query_bbox['maxx'],  query_bbox['maxy'])
+
+        tileRef['t_cols_offset'] = int(self.tile_cols * self.i_x)
+        tileRef['t_rows_offset'] = int(self.tile_rows * self.i_y)
+
+        if self.i_y >= self.num_tiles_y - 1:
+            self.i_y = 0
+            self.i_x += 1
+            # set bbox for next tile (E, W)      
+            self.tile_bbox['maxx'] += self.tile_length_x 
+            self.tile_bbox['minx'] += self.tile_length_x 
+        else:
+            self.i_y += 1
+
+        return query_url, tileRef
+
+    def _flipBbox(self, bbox, proj, version):
+        """ 
+        Flips coordinates if WMS standard is 1.3.0 and 
+        projection is geographic.
+
+        value flips between this keys:
+        maxy -> maxx
+        maxx -> maxy
+        miny -> minx
+        minx -> miny
+        @return copy of bbox with flipped coordinates
+        """  
+
+        temp_bbox = dict(bbox)
+        new_bbox = {}
+        new_bbox['maxy'] = temp_bbox['maxx']
+        new_bbox['miny'] = temp_bbox['minx']
+        new_bbox['maxx'] = temp_bbox['maxy']
+        new_bbox['minx'] = temp_bbox['miny']
+
+        return new_bbox
+
+
+class WMTSRequestMgr(BaseRequestMgr):
+    def __init__(self, params, bbox, region, proj_srs, cap_file = None):
+        """!Initializes data needed for iteration through tiles.
+        """
+
+        self.proj_srs = proj_srs
+        self.meters_per_unit = None
+
+        # constant defined in WMTS standard (in meters)
+        self.pixel_size = 0.00028
+
+        # parse capabilities file
+        cap_tree = etree.parse(cap_file)
+        root = cap_tree.getroot()
+
+        # get layer tile matrix sets with same projection
+        mat_sets = self._getMatSets(root, params)
+
+        # TODO: what if more tile matrix sets are returned?
+        params['tile_matrix_set'] = mat_sets[0].find(self._ns_ows('Identifier')).text
+
+        # find tile matrix with resolution closest and smaller to wanted resolution 
+        tile_mat  = self._findTileMats(mat_sets[0].findall(self._ns_wmts('TileMatrix')), region, bbox)
+
+        # initialize data needed for iteration through tiles
+        self._computeRequestData(tile_mat, params, bbox)
+
+    def GetMapRegion(self):
+        """!Get size in pixels and bounding box of raster where all tiles will be merged.
+        """
+        return self.map_region
+
+    def _getMatSets(self, root, params):
+        """!Get matrix sets which are available for chosen layer and have required EPSG.
+        """
+        contents = self.find(root, 'Contents', self._ns_wmts)
+        layers = self.findall(contents, 'Layer', self._ns_wmts)
+
+        ch_layer = None
+        for layer in layers:
+            layer_id = layer.find(self._ns_ows('Identifier')).text
+            if layer_id and layer_id == params['layers']:
+                ch_layer = layer 
+                break  
+
+        if ch_layer is None:
+            grass.fatal(_("Layer '%s' was not found in capabilities file") % params['layers'])
+
+        mat_set_links = self.findall(ch_layer, 'TileMatrixSetLink', self._ns_wmts)
+
+        suitable_mat_sets = []
+        tileMatrixSets = self.findall(contents, 'TileMatrixSet', self._ns_wmts)
+
+        for link in  mat_set_links:
+            mat_set_link_id = link.find(self._ns_wmts('TileMatrixSet')).text
+            if not mat_set_link_id:
+                continue
+            for mat_set in tileMatrixSets:
+                mat_set_id = mat_set.find(self._ns_ows('Identifier')).text 
+                if mat_set_id and mat_set_id != mat_set_link_id:
+                    continue
+                mat_set_srs = mat_set.find(self._ns_ows('SupportedCRS')).text
+                if mat_set_srs and mat_set_srs.lower() == ("EPSG:"+ str(params['srs'])).lower():
+                    suitable_mat_sets.append(mat_set)
+
+        if not suitable_mat_sets:
+            grass.fatal(_("Layer '%s' is not available with %s code.") % (params['layers'],  "EPSG:" + str(params['srs'])))
+
+        return suitable_mat_sets
+
+    def _findTileMats(self, tile_mats, region, bbox):
+        """!Find tile matrix set with closest and smaller resolution to requested resolution
+        """        
+        scale_dens = []
+
+        scale_dens.append((bbox['maxy'] - bbox['miny']) / region['rows'] * self._getMetersPerUnit()  / self.pixel_size)
+        scale_dens.append((bbox['maxx'] - bbox['minx']) / region['cols'] * self._getMetersPerUnit() / self.pixel_size)
+
+        scale_den = min(scale_dens)
+
+        first = True
+        for t_mat in tile_mats:
+            mat_scale_den = float(t_mat.find(self._ns_wmts('ScaleDenominator')).text)
+            if first:
+                best_scale_den = mat_scale_den
+                best_t_mat = t_mat
+                first = False
+                continue
+                
+            best_diff = best_scale_den - scale_den
+            mat_diff = mat_scale_den - scale_den
+            if (best_diff < mat_diff  and  mat_diff < 0) or \
+               (best_diff > mat_diff  and  best_diff > 0):
+                best_t_mat = t_mat
+                best_scale_den = mat_scale_den
+
+        return best_t_mat
+
+    def _getMetersPerUnit(self):
+        """!Get coefficient which allows to convert units of request projection into meters 
+        """  
+        if self.meters_per_unit:
+            return self.meters_per_unit
+
+        # for geographic projection
+        if self._isGeoProj(self.proj_srs):
+            proj_params = proj_srs.split(' ')
+            for param in proj_parmas:
+                if '+a' in param:
+                    a = float(param.split('=')[1])
+                    break
+            equator_perim = 2 * pi * a
+            # meters per degree on equator
+            self.meters_per_unit = equator_perim / 360 
+
+        # other units
+        elif '+to_meter' in self.proj_srs:
+            proj_params = self.proj_srs.split(' ')
+            for param in proj_params:
+                if '+to_meter' in param:
+                    self.meters_per_unit = 1/float(param.split('=')[1])
+                    break
+        # coordinate system in meters        
+        else:
+            self.meters_per_unit = 1
+
+        return self.meters_per_unit
+
+    def _computeRequestData(self, tile_mat, params, bbox):
+        """!Initialize data needed for iteration through tiles.
+        """  
+        scale_den = float(tile_mat.find(self._ns_wmts('ScaleDenominator')).text)
+
+        pixel_span = scale_den * self.pixel_size / self._getMetersPerUnit()
+
+        tl_corner = tile_mat.find(self._ns_wmts('TopLeftCorner')).text.split(' ')
+
+        self.t_cols = int(tile_mat.find(self._ns_wmts('TileWidth')).text)
+        t_length_x = pixel_span * self.t_cols
+        
+        self.t_rows = int(tile_mat.find(self._ns_wmts('TileHeight')).text)
+        t_length_y = pixel_span * self.t_rows
+    
+        t_mat_min_x = float(tl_corner[0])
+        t_mat_max_y = float(tl_corner[1])
+        
+        epsilon = 2e-15
+
+        self.t_num_bbox = {}
+        self.t_num_bbox['min_col'] = int(floor((bbox['minx'] - t_mat_min_x) / t_length_x + epsilon))
+        self.t_num_bbox['max_col'] = int(floor((bbox['maxx'] - t_mat_min_x) / t_length_x - epsilon))
+
+        self.t_num_bbox['min_row'] = int(floor((t_mat_max_y - bbox['maxy']) / t_length_y + epsilon))
+        self.t_num_bbox['max_row'] = int(floor((t_mat_max_y - bbox['miny']) / t_length_y - epsilon))
+
+        matWidth = int(tile_mat.find(self._ns_wmts('MatrixWidth')).text)
+        matHeight = int(tile_mat.find(self._ns_wmts('MatrixHeight')).text)
+
+        self.intersects = False
+        for col in ['min_col', 'max_col']:
+            for row in ['min_row', 'max_row']:
+                if (0 <= self.t_num_bbox[row] and self.t_num_bbox[row] <= matHeight) and \
+                   (0 <= self.t_num_bbox[col] and self.t_num_bbox[col] <= matWidth):
+                    self.intersects = True
+                    
+        if not self.intersects:
+            grass.warning(_('Region is out of server data extend.'))
+            self.map_region = None
+            return
+
+        if self.t_num_bbox['min_col'] < 0:
+            self.t_num_bbox['min_col']  = 0
+
+        if self.t_num_bbox['max_col'] > (matWidth - 1):
+            self.t_num_bbox['max_col']  = matWidth - 1
+
+        if self.t_num_bbox['min_row'] < 0:
+            self.t_num_bbox['min_row']  = 0
+
+        if self.t_num_bbox['max_row'] > (matHeight - 1):
+            self.t_num_bbox['max_row'] = matHeight - 1
+
+        num_tiles = (self.t_num_bbox['max_col'] - self.t_num_bbox['min_col'] + 1) * (self.t_num_bbox['max_row'] - self.t_num_bbox['min_row'] + 1) 
+        grass.message(_('Fetching %d tiles with %d x %d pixel size per tile...') % (num_tiles, self.t_cols, self.t_rows))
+
+        self.url = params['url'] + ("?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&" \
+                                    "LAYER=%s&STYLE=%s&FORMAT=%s&TILEMATRIXSET=%s&TILEMATRIX=%s" % \
+                                   (params['layers'], params['styles'], params['format'],
+                                    params['tile_matrix_set'], tile_mat.find(self._ns_ows('Identifier')).text ))
+
+        if params['urlparams'] != "":
+            self.url += "&" + params['urlparams']
+
+        self.map_region = {}
+        self.map_region['minx'] = self.t_num_bbox['min_col'] * t_length_x + t_mat_min_x
+        self.map_region['maxy'] = t_mat_max_y - (self.t_num_bbox['min_row']) * t_length_y
+
+        self.map_region['maxx'] = (self.t_num_bbox['max_col'] + 1) * t_length_x + t_mat_min_x
+        self.map_region['miny'] = t_mat_max_y - (self.t_num_bbox['max_row'] + 1) * t_length_y
+
+        self.map_region['cols'] = self.t_cols * (self.t_num_bbox['max_col'] -  self.t_num_bbox['min_col'] + 1)
+        self.map_region['rows'] = self.t_rows * (self.t_num_bbox['max_row'] -  self.t_num_bbox['min_row'] + 1)
+
+        self.i_col = self.t_num_bbox['min_col']
+        self.i_row = self.t_num_bbox['min_row'] 
+
+        self.tileRef = {
+                          'sizeX' : self.t_cols,
+                          'sizeY' : self.t_rows
+                        }
+
+    def GetNextTile(self):
+        """!Get url for request the tile from server and information for merging the tile with other tiles
+        """
+        if not self.intersects or self.i_col > self.t_num_bbox['max_col']:
+            return None 
+                
+        query_url = self.url + "&TILECOL=%i&TILEROW=%i" % (int(self.i_col), int(self.i_row)) 
+
+        self.tileRef['t_cols_offset'] = int(self.t_cols * (self.i_col - self.t_num_bbox['min_col']))
+        self.tileRef['t_rows_offset'] = int(self.t_rows * (self.i_row - self.t_num_bbox['min_row']))
+
+        if self.i_row >= self.t_num_bbox['max_row']:
+            self.i_row =  self.t_num_bbox['min_row']
+            self.i_col += 1
+        else:
+            self.i_row += 1 
+
+        return query_url, self.tileRef
+
+    def _ns_wmts(self, tag):
+        """!Helper method - XML namespace
+        """       
+        return "{http://www.opengis.net/wmts/1.0}" + tag
+
+    def _ns_ows(self, tag):
+        """!Helper method - XML namespace
+        """
+        return "{http://www.opengis.net/ows/1.1}" + tag

Added: grass-addons/grass7/grass7/raster/r.in.wms2/wms_gdal_drv.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.in.wms2/wms_gdal_drv.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.in.wms2/wms_gdal_drv.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,139 @@
+import os
+import grass.script as grass 
+
+try:
+    from osgeo import gdal
+    from osgeo import gdalconst
+except:
+    grass.fatal(_("Unable to load GDAL Python bindings"))
+
+import xml.etree.ElementTree as etree
+
+from wms_base import WMSBase
+
+class NullDevice():
+    def write(self, s):
+        pass
+
+class WMSGdalDrv(WMSBase):
+    def _createXML(self):
+        """!Create XML for GDAL WMS driver
+        
+        @return path to XML file
+        """
+        self._debug("_createXML", "started")
+        
+        gdal_wms = etree.Element("GDAL_WMS")
+        service = etree.SubElement(gdal_wms, "Service")
+        name = etree.Element("name")
+        service.set("name","WMS")
+        
+        version = etree.SubElement(service, "Version")
+        version.text =self.params['wms_version']
+        
+        server_url = etree.SubElement(service, "ServerUrl")
+        server_url.text =self.params['url']
+        
+        srs = etree.SubElement(service, self.params['proj_name'])   
+        srs.text = 'EPSG:' + str(self.params['srs'])
+        
+        image_format = etree.SubElement(service, "ImageFormat")
+        image_format.text = self.params['format']
+        
+        image_format = etree.SubElement(service, "Transparent")
+        image_format.text = self.params['transparent']
+        
+        layers = etree.SubElement(service, "Layers")
+        layers.text = self.params['layers']
+        
+        styles = etree.SubElement(service, "Styles")
+        styles.text = self.params['styles']
+        
+        data_window = etree.SubElement(gdal_wms, "DataWindow")
+        
+        upper_left_x = etree.SubElement(data_window, "UpperLeftX")
+        upper_left_x.text = str(self.bbox['minx']) 
+        
+        upper_left_y = etree.SubElement(data_window, "UpperLeftY")
+        upper_left_y.text = str(self.bbox['maxy']) 
+        
+        lower_right_x = etree.SubElement(data_window, "LowerRightX")
+        lower_right_x.text = str(self.bbox['maxx']) 
+        
+        lower_right_y = etree.SubElement(data_window, "LowerRightY")
+        lower_right_y.text = str(self.bbox['miny'])
+        
+        size_x = etree.SubElement(data_window, "SizeX")
+        size_x.text = str(self.region['cols']) 
+        
+        size_y = etree.SubElement(data_window, "SizeY")
+        size_y.text = str(self.region['rows']) 
+        
+        # RGB + alpha
+        self.temp_map_bands_num = 4
+        block_size_x = etree.SubElement(gdal_wms, "BandsCount")
+        block_size_x.text = str(self.temp_map_bands_num)
+        
+        block_size_x = etree.SubElement(gdal_wms, "BlockSizeX")
+        block_size_x.text = str(self.tile_size['cols']) 
+        
+        block_size_y = etree.SubElement(gdal_wms, "BlockSizeY")
+        block_size_y.text = str(self.tile_size['rows'])
+        
+        xml_file = self._tempfile()
+        
+        etree.ElementTree(gdal_wms).write(xml_file)
+        
+        self._debug("_createXML", "finished -> %s" % xml_file)
+        
+        return xml_file
+    
+    def _download(self):
+        """!Downloads data from WMS server using GDAL WMS driver
+        
+        @return temp_map with stored downloaded data
+        """
+        grass.message("Downloading data from WMS server...")
+
+        # GDAL WMS driver does not flip geographic coordinates 
+        # according to WMS standard 1.3.0.
+        if ("+proj=latlong" in self.proj_srs or \
+            "+proj=longlat" in self.proj_srs) and \
+            self.params['wms_version'] == "1.3.0":
+            grass.warning(_("If module will not be able to fetch the data in this\
+                           geographic projection, \n try 'WMS_GRASS' driver or use WMS version 1.1.1."))
+
+        self._debug("_download", "started")
+        
+        temp_map = self._tempfile()        
+
+        xml_file = self._createXML()
+        wms_dataset = gdal.Open(xml_file, gdal.GA_ReadOnly)
+        grass.try_remove(xml_file)
+        if wms_dataset is None:
+            grass.fatal(_("Unable to open GDAL WMS driver"))
+        
+        self._debug("_download", "GDAL dataset created")
+        
+        driver = gdal.GetDriverByName(self.gdal_drv_format)
+        if driver is None:
+            grass.fatal(_("Unable to find %s driver" % format))
+        
+        metadata = driver.GetMetadata()
+        if not metadata.has_key(gdal.DCAP_CREATECOPY) or \
+           metadata[gdal.DCAP_CREATECOPY] == 'NO':
+            grass.fatal(_('Driver %s supports CreateCopy() method.') % self.gdal_drv_name)
+        
+        self._debug("_download", "calling GDAL CreateCopy...")
+        
+        temp_map_dataset = driver.CreateCopy(temp_map, wms_dataset, 0)
+        
+        if temp_map_dataset is None:
+            grass.fatal(_("Incorrect WMS query"))
+        
+        temp_map_dataset  = None
+        wms_dataset = None
+        
+        self._debug("_download", "finished")
+        
+        return temp_map

Added: grass-addons/grass7/grass7/raster/r.massmov/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.massmov
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
+

Added: grass-addons/grass7/grass7/raster/r.massmov/filters.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/filters.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/filters.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,353 @@
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+
+#define nullo -999.9f
+
+float gradx3(float **matrix, int row, int col, float dx, int abs) {
+	float v;
+
+	if (matrix[row][col] != nullo && matrix[row][col + 1] != nullo
+			&& matrix[row - 1][col + 1] != nullo
+			&& matrix[row + 1][col + 1] != nullo
+			&& matrix[row][col - 1] != nullo
+			&& matrix[row - 1][col - 1] != nullo
+			&& matrix[row + 1][col - 1] != nullo) {
+
+		if (abs == 1){
+			v = (fabs((matrix[row - 1][col + 1]) + 2 * fabs(matrix[row][col + 1])
+							+ fabs(matrix[row + 1][col + 1]))
+							- (fabs(matrix[row - 1][col - 1]) + 2 * fabs(matrix[row][col - 1])
+									+ fabs(matrix[row + 1][col - 1]))) / (8 * dx);
+			return v;
+		}
+		else{
+			v = ((matrix[row - 1][col + 1] + 2 * matrix[row][col + 1]
+										+ matrix[row + 1][col + 1])
+										- (matrix[row - 1][col - 1] + 2 * matrix[row][col - 1]
+												+ matrix[row + 1][col - 1])) / (8 * dx);
+			return v;
+		}
+	} else {
+		return nullo;
+	}
+}
+
+float grady3(float **matrix, int row, int col, float dy, int abs) {
+	float v;
+
+	if (matrix[row][col] != nullo && matrix[row - 1][col - 1] != nullo
+			&& matrix[row - 1][col] != nullo
+			&& matrix[row - 1][col + 1] != nullo
+			&& matrix[row + 1][col - 1] != nullo
+			&& matrix[row + 1][col] != nullo
+			&& matrix[row + 1][col + 1] != nullo) {
+
+		if (abs == 1){
+			v = ((fabs(matrix[row - 1][col - 1]) + 2 * fabs(matrix[row - 1][col])
+							+ fabs(matrix[row - 1][col + 1]))
+							- fabs((matrix[row + 1][col - 1]) + 2 * fabs(matrix[row + 1][col])
+									+ fabs(matrix[row + 1][col + 1]))) / (8 * dy);
+			return v;
+		}
+		else {
+			v = ((matrix[row - 1][col - 1] + 2 * matrix[row - 1][col]
+										+ matrix[row - 1][col + 1])
+										- (matrix[row + 1][col - 1] + 2 * matrix[row + 1][col]
+												+ matrix[row + 1][col + 1])) / (8 * dy);
+			return v;
+		}
+
+	} else {
+		return nullo;
+	}
+}
+
+float gradx2(float **matrix, int row, int col, float dx, int abs) {
+	float v;
+
+	if (matrix[row][col] != nullo && matrix[row][col + 1] != nullo
+			&& matrix[row][col - 1] != nullo) {
+
+		if (abs == 1){
+			v = (fabs(matrix[row][col + 1]) - fabs(matrix[row][col - 1])) / (2 * dx);
+			return v;
+		}
+		else {
+			v = (matrix[row][col + 1] - matrix[row][col - 1]) / (2 * dx);
+			return v;
+		}
+	} else {
+		return nullo;
+	}
+}
+
+float gradPx2(float **matrix1, float **matrix2, float **matrix3, int row,
+		int col, float dx) {
+	float v;
+
+	if (matrix1[row][col] != nullo && matrix2[row][col] != nullo
+			&& (cos(atan(matrix3[row][col]))) != nullo
+			&& matrix1[row][col + 1] != nullo && matrix2[row][col + 1] != nullo
+			&& (cos(atan(matrix3[row][col + 1]))) != nullo
+			&& matrix1[row][col - 1] != nullo && matrix2[row][col - 1] != nullo
+			&& (cos(atan(matrix3[row][col - 1]))) != nullo) {
+		v = ((9.8 * (matrix1[row][col + 1] + matrix2[row][col + 1])
+				* (cos(atan(matrix3[row][col + 1]))))
+				- (9.8 * (matrix1[row][col - 1] + matrix2[row][col - 1])
+						* (cos(atan(matrix3[row][col - 1]))))) / (2 * dx);
+		return v;
+
+	} else
+		return nullo;
+}
+
+float grady2(float **matrix, int row, int col, float dy, int abs) {
+	float v;
+
+	if (matrix[row][col] != nullo && matrix[row + 1][col] != nullo
+			&& matrix[row - 1][col] != nullo) {
+
+		if (abs == 1){
+			v = (fabs(matrix[row - 1][col]) - fabs(matrix[row + 1][col])) / (2 * dy);
+			return v;
+		}
+
+		else {
+			v = (matrix[row - 1][col] - matrix[row + 1][col]) / (2 * dy);
+			return v;
+		}
+	} else {
+		return nullo;
+	}
+}
+
+/* calcolo del gradiente combinato della somma di 2 matrici (usato per P)
+ * gradPy2 (pendenza y, matrice 1, matrice 2, riga, col, res y)
+ *
+ * */
+float gradPy2(float **matrix1, float **matrix2, float **matrix3, int row,
+		int col, float dy) {
+	float v;
+
+	if (matrix1[row][col] != nullo && matrix2[row][col] != nullo
+			&& (cos(atan(matrix3[row][col]))) != nullo
+			&& matrix1[row + 1][col] != nullo && matrix2[row + 1][col] != nullo
+			&& (cos(atan(matrix3[row + 1][col]))) != nullo
+			&& matrix1[row - 1][col] != nullo && matrix2[row - 1][col] != nullo
+			&& (cos(atan(matrix3[row - 1][col]))) != nullo) {
+		v = ((9.8 * (matrix1[row - 1][col] + matrix2[row - 1][col])
+				* (cos(atan(matrix3[row - 1][col]))))
+				- (9.8 * (matrix1[row + 1][col] + matrix2[row + 1][col])
+						* (cos(atan(matrix3[row + 1][col]))))) / (2 * dy);
+		return v;
+
+	} else
+		return nullo;
+}
+
+float lax(float **matrix, int row, int col, float laxfactor) {
+
+	float gg = 0.0;
+	float hh = 0.0;
+	float v;
+
+	if (matrix[row][col] != nullo) {
+
+		if (matrix[row - 1][col - 1] != nullo) {
+			gg = gg + 2 * matrix[row - 1][col - 1];
+			hh = hh + 2;
+		}
+
+
+		if (matrix[row - 1][col] != nullo) {
+			gg = gg + 3 * matrix[row - 1][col];
+			hh = hh + 3;
+		}
+
+		if (matrix[row - 1][col + 1] != nullo) {
+			gg = gg + 2 * matrix[row - 1][col + 1];
+			hh = hh + 2;
+		}
+
+		if (matrix[row][col - 1] != nullo) {
+			gg = gg + 3 * matrix[row][col - 1];
+			hh = hh + 3;
+		}
+
+		if (matrix[row][col + 1] != nullo) {
+			gg = gg + 3 * matrix[row][col + 1];
+			hh = hh + 3;
+		}
+
+		if (matrix[row + 1][col - 1] != nullo) {
+			gg = gg + 2 * matrix[row + 1][col - 1];
+			hh = hh + 2;
+		}
+
+		if (matrix[row + 1][col] != nullo) {
+			gg = gg + 3 * matrix[row + 1][col];
+			hh = hh + 3;
+		}
+
+		if (matrix[row + 1][col + 1] != nullo) {
+			gg = gg + 2 * matrix[row + 1][col + 1];
+			hh = hh + 2;
+		}
+
+		if (/*gg != 0.0 &&*/ hh != 0.0)
+			v = ((1 - laxfactor) * matrix[row][col] + laxfactor * (gg / hh));
+		else
+			v = matrix[row][col];
+
+		return v;
+	}
+
+	else {
+		return nullo;
+	}
+
+}
+
+float filter_lax(float **matrix, int row, int col, float laxfactor, float **filter_matrix,float threshold,float val) {
+
+
+	float gg = 0.0;
+	float hh = 0.0;
+	float v;
+
+
+	if (matrix[row][col] != nullo && (filter_matrix[row][col] > threshold)) {
+
+		if ((matrix[row - 1][col - 1] != nullo)&&(filter_matrix[row - 1][col - 1] > threshold)) {
+			gg = gg + 2 * matrix[row - 1][col - 1];
+			hh = hh + 2;
+		}
+
+
+		if ((matrix[row - 1][col] != nullo)&&(filter_matrix[row - 1][col] > threshold)) {
+			gg = gg + 3 * matrix[row - 1][col];
+			hh = hh + 3;
+		}
+
+		if ((matrix[row - 1][col + 1] != nullo)&&(filter_matrix[row - 1][col + 1] > threshold)) {
+			gg = gg + 2 * matrix[row - 1][col + 1];
+			hh = hh + 2;
+		}
+
+		if ((matrix[row][col - 1] != nullo)&&(filter_matrix[row][col - 1] > threshold)) {
+			gg = gg + 3 * matrix[row][col - 1];
+			hh = hh + 3;
+		}
+
+		if ((matrix[row][col + 1] != nullo)&&(filter_matrix[row][col + 1] > threshold)) {
+			gg = gg + 3 * matrix[row][col + 1];
+			hh = hh + 3;
+		}
+
+		if ((matrix[row + 1][col - 1] != nullo)&&(filter_matrix[row + 1][col - 1] > threshold)) {
+			gg = gg + 2 * matrix[row + 1][col - 1];
+			hh = hh + 2;
+		}
+
+		if ((matrix[row + 1][col] != nullo)&&(filter_matrix[row + 1][col] > threshold)) {
+			gg = gg + 3 * matrix[row + 1][col];
+			hh = hh + 3;
+		}
+
+		if ((matrix[row + 1][col + 1] != nullo)&&(filter_matrix[row + 1][col + 1] > threshold)) {
+			gg = gg + 2 * matrix[row + 1][col + 1];
+			hh = hh + 2;
+		}
+
+		if (/*gg != 0.0 &&*/ hh != 0.0)
+			v = ((1 - laxfactor) * matrix[row][col] + laxfactor * (gg / hh));
+		else
+			v = matrix[row][col];
+
+		return v;
+	}
+
+	else {
+		v=val;
+		return v;
+	}
+
+}
+
+
+float filter_lax_print(float **matrix, int row, int col, float laxfactor, float **filter_matrix,float threshold,float val) {
+
+
+	float gg = 0.0;
+	float hh = 0.0;
+	float v;
+
+	if (matrix[row][col] != nullo && (filter_matrix[row][col] > threshold)) {
+		if ((matrix[row - 1][col - 1] != nullo)&&(filter_matrix[row - 1][col - 1] > threshold)) {
+			gg = gg + 2 * matrix[row - 1][col - 1];
+			hh = hh + 2;
+			while (getchar() != 'y') {}
+		}
+
+
+		if ((matrix[row - 1][col] != nullo)&&(filter_matrix[row - 1][col] > threshold)) {
+			gg = gg + 3 * matrix[row - 1][col];
+			hh = hh + 3;
+			while (getchar() != 'y') {}
+		}
+
+		if ((matrix[row - 1][col + 1] != nullo)&&(filter_matrix[row - 1][col + 1] > threshold)) {
+			gg = gg + 2 * matrix[row - 1][col + 1];
+			hh = hh + 2;
+			while (getchar() != 'y') {}
+		}
+
+		if ((matrix[row][col - 1] != nullo)&&(filter_matrix[row][col - 1] > threshold)) {
+			gg = gg + 3 * matrix[row][col - 1];
+			hh = hh + 3;
+			while (getchar() != 'y') {}
+		}
+
+		if ((matrix[row][col + 1] != nullo)&&(filter_matrix[row][col + 1] > threshold)) {
+			gg = gg + 3 * matrix[row][col + 1];
+			hh = hh + 3;
+			while (getchar() != 'y') {}
+		}
+
+		if ((matrix[row + 1][col - 1] != nullo)&&(filter_matrix[row + 1][col - 1] > threshold)) {
+			gg = gg + 2 * matrix[row + 1][col - 1];
+			hh = hh + 2;
+			while (getchar() != 'y') {}
+		}
+
+		if ((matrix[row + 1][col] != nullo)&&(filter_matrix[row + 1][col] > threshold)) {
+			gg = gg + 3 * matrix[row + 1][col];
+			hh = hh + 3;
+			while (getchar() != 'y') {}
+		}
+
+		if ((matrix[row + 1][col + 1] != nullo)&&(filter_matrix[row + 1][col + 1] > threshold)) {
+			gg = gg + 2 * matrix[row + 1][col + 1];
+			hh = hh + 2;
+			while (getchar() != 'y') {}
+		}
+
+		if (/*gg != 0.0 &&*/ hh != 0.0)
+			v = ((1 - laxfactor) * matrix[row][col] + laxfactor * (gg / hh));
+		else
+			v = matrix[row][col];
+
+		return v;
+	}
+
+	else {
+		v=val;
+		return v;
+	}
+}

Added: grass-addons/grass7/grass7/raster/r.massmov/filters.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/filters.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/filters.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,12 @@
+float gradx3(float **matrix, int row, int col, float dx, int abs);
+float grady3(float **matrix, int row, int col, float dy, int abs);
+float gradx2(float **matrix, int row, int col, float dx, int abs);
+float grady2(float **matrix, int row, int col, float dy, int abs);
+float lax(float **matrix, int row, int col, float laxfactor);
+float filter_lax(float **matrix, int row, int col, float laxfactor, float **filter_matrix,float threshold,float val);
+float gradPx2(float **matrix1, float **matrix2, float **matrix3, int row,
+		int col, float dx);
+float gradPy2(float **matrix1, float **matrix2, float **matrix3, int row,
+		int col, float dy);
+float isocell(float **matrix,int row,int col,float val);
+float filter_lax_print(float **matrix, int row, int col, float laxfactor, float **filter_matrix,float threshold,float val);

Added: grass-addons/grass7/grass7/raster/r.massmov/general_f.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/general_f.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/general_f.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,261 @@
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include <grass/linkm.h>
+
+#define HBExp 1
+#define verysmall 0.01
+#define min(A,B) ((A) < (B) ? (A):(B))
+#define max(A,B) ((A) > (B) ? (A):(B))
+
+float **G_alloc_fmatrix(int rows, int cols) {
+	float **m;
+	int i;
+	m = (float **) G_calloc(rows, sizeof(float *));
+	m[0] = (float *) G_calloc(rows * cols, sizeof(float));
+	for (i = 1; i < rows; i++)
+		m[i] = m[i - 1] + cols;
+	return m;
+}
+
+int **G_alloc_imatrix(int rows, int cols) {
+	int **mmm;
+	int i;
+	mmm = (int **) G_calloc(rows, sizeof(int *));
+	mmm[0] = (int *) G_calloc(rows * cols, sizeof(int));
+	for (i = 1; i < rows; i++)
+		mmm[i] = mmm[i - 1] + cols;
+	return mmm;
+}
+
+void G_free_fmatrix(float **m) {
+	G_free(m[0]);
+	G_free(m);
+	m = NULL;
+	return;
+}
+
+void G_free_imatrix(int **mmm) {
+	G_free(mmm[0]);
+	G_free(mmm);
+	mmm = NULL;
+	return;
+}
+
+int check_rheol_par(int rheol_type, float chezy, float visco, float rho) {
+	if (rheol_type == 2) {
+		if (chezy > 0)
+			return 1;
+		else
+			return -2;
+	}
+
+	if (rheol_type == 3) {
+		if (visco > 0 && rho > 0)
+			return 1;
+		else
+			return -3;
+	}
+}
+
+float t_frict(float **h, int row, int col, float b_frict) {
+	float t;
+
+	if (h[row][col] > verysmall) {
+		t = tan((M_PI * b_frict) / 180.0);
+	} else {
+		t = 5 * tan((M_PI * b_frict) / 180.0);
+	}
+	return t;
+}
+
+float t_voellmy(float v, float **h, int row, int col, float b_frict,
+		float chezy) {
+	float t;
+	if (h[row][col] > verysmall) {
+		t = tan((M_PI * b_frict) / 180.0) + pow(v, 2) / (chezy * h[row][col]);
+	} else {
+		t = 5 * tan((M_PI * b_frict) / 180.0);
+	}
+	return t;
+}
+
+float t_visco(float v, float **h, int row, int col, float b_frict, float rho,
+		float visco, float ystress) {
+	float t;
+
+	if (h[row][col] > verysmall) {
+		if (ystress > 0) {
+			t =
+					tan((M_PI * b_frict) / 180.0)
+							+ (1.5 * ystress
+									+ (3 * visco * pow(v, HBExp) / h[row][col]))
+									/ (rho * h[row][col]);
+		} else {
+			t = tan((M_PI * b_frict) / 180.0)
+					+ (3 * visco * pow(v, HBExp) / h[row][col] / h[row][col]);
+		}
+	} else {
+		if (ystress > 0) {
+			t = 5 * ystress;
+		} else {
+			t = 5 * tan((M_PI * b_frict) / 180.0);  ///// CHECK settare a 0  ???
+		}
+	}
+	return t;
+}
+
+
+float veldt(float ua, float t, float g_x, float p_x, float i_x, float t_x) {
+	float v;
+
+	if (ua>0)
+		v = max(0, ua + t * (g_x + p_x + i_x - t_x));
+
+	else if (ua<0)
+		v = min(ua + t * (g_x + p_x - i_x + t_x),0);
+
+	else {
+		if ((g_x+p_x)>0)
+			v = max(0, t * (g_x + p_x + i_x - t_x));
+
+		else if ((g_x+p_x)<0){
+			v = min(t * (g_x + p_x - i_x + t_x),0);
+		}
+		else
+			v=0;
+	}
+
+	return v;
+}
+
+float shift0(float **m, int r, int c, int maxR, int maxC, int minR, int minC, int n, int w) {
+	float v;
+
+	if ((r+n<minR) || (r+n>maxR))
+		v=0;
+	else if ((c+w<minC)|| (c+w>maxC))
+		v=0;
+	else
+		v = m[r+n][c+w];
+
+	return v;
+}
+
+
+void out_print (float **matrix,char *name, int nr, int nc){
+	int row,col;
+	float *outrast;
+	int outfd;
+
+	outrast = Rast_allocate_f_buf();
+	outfd = Rast_open_fp_new(name);
+	for (row = 0; row < nr; row++) {
+		for (col = 0; col < nc; col++) {
+			if (matrix[row][col]==0)
+				Rast_set_f_null_value(&outrast[col], 1);
+			else
+				((FCELL *) outrast)[col] = matrix[row][col];
+		}
+		Rast_put_f_row(outfd, outrast);
+	}
+	G_free(outrast);
+	Rast_close(outfd);
+}
+
+
+void out_sum_print (float **matrix1, float **matrix2, float **matrix3, float **matrix4,char *name, int nr, int nc, int mode, float threshold){
+	int row,col;
+	float *outrast;
+	int outfd;
+	/*struct History history; * holds meta-data */
+	
+	outrast = Rast_allocate_f_buf();
+	outfd = Rast_open_fp_new(name);
+	for (row = 0; row < nr; row++) {
+		for (col = 0; col < nc; col++) {
+			if (mode==1){
+				if (matrix1[row][col]+matrix2[row][col]>0)
+					((FCELL *) outrast)[col] = matrix1[row][col]+matrix2[row][col];
+				else
+					Rast_set_f_null_value(&outrast[col], 1);
+				}
+			if (mode==2){
+				if (matrix1[row][col]+matrix2[row][col]>0)
+					if (matrix2[row][col]>threshold)
+						((FCELL *) outrast)[col] = sqrt(pow(matrix3[row][col],2)+pow(matrix4[row][col],2));
+					else
+						((FCELL *) outrast)[col] = 0.0;
+				else
+					Rast_set_f_null_value(&outrast[col], 1);
+				}
+			}
+		Rast_put_f_row(outfd, outrast);
+		/**
+		Rast_short_history(name, "raster", &history);
+		Rast_command_history(&history);
+		Rast_write_history(name, &history);
+		**/
+	}
+	G_free(outrast);
+	Rast_close(outfd);
+}
+
+float nash_sutcliffe(float **m_t1,float**m_t2, int nr, int nc){
+	float sum_den=0;
+	float sum_num=0;
+	float sum_ave=0;
+	int row,col,c=0;
+	float ns_res,ave;
+
+	for (row = 0; row < nr; row++) {
+		for (col = 0; col < nc; col++) {
+			sum_ave +=m_t1[row][col];
+			c+=1;
+		}
+	}
+
+	ave = sum_ave/c;
+
+	for (row = 0; row < nr; row++) {
+		for (col = 0; col < nc; col++) {
+			sum_num += pow(m_t1[row][col]-m_t2[row][col],2);
+			sum_den += pow(m_t1[row][col]-ave,2);
+		}
+	}
+	if (sum_den==0){
+		ns_res = -9999999;
+		G_message("WARNING: -inf value obtained for NS coefficient; the new value -9999999 has been set");
+	} else {
+		ns_res = 1 - (sum_num/sum_den);
+	}
+	return ns_res;
+}
+
+
+void report_input(float ifrict,float rho,float ystress,float visco,float chezy,float bfrict,float fluid,float NS_thres,int t,int delta){
+	fprintf(stdout, "-----------Input data:-----------\n");
+	fprintf(stdout, "Internal friction angle = %.2f\n",ifrict);
+	if (rho!=-1)
+		fprintf(stdout, "Density = %.2f\n",rho);
+	if (ystress!=-1)
+		fprintf(stdout, "Yield stress = %.2f\n",ystress);
+	if (visco!=-1)
+		fprintf(stdout, "Viscosity = %.2f\n",visco);
+	if (chezy!=-1)
+		fprintf(stdout, "Chézy coefficient = %.2f\n",chezy);
+	if (bfrict!=-1)
+		fprintf(stdout, "Basal friction angle = %.2f\n",bfrict);
+	if (fluid!=-1)
+		fprintf(stdout, "Fluidization rate = %.2f\n",fluid);
+	if (NS_thres!=-1)
+		fprintf(stdout, "Nash-Sutcliffe threshold = %.4f\n",NS_thres);
+	fprintf(stdout, "Maximum timesteps number  = %i\n",t);
+	if (delta!=-1)
+		fprintf(stdout, "Reporting time frequency = %i\n",delta);
+	fprintf(stdout, "---------------------------------\n");
+}

Added: grass-addons/grass7/grass7/raster/r.massmov/general_f.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/general_f.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/general_f.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,16 @@
+float **G_alloc_fmatrix(int rows, int cols);
+int **G_alloc_imatrix(int rows, int cols);
+void G_free_fmatrix(float **m);
+void G_free_imatrix(int **mmm);
+int check_rheol_par(int rheol_type, float chezy, float visco, float rho);
+float t_frict(float **h, int row, int col, float b_frict);
+float t_voellmy(float vel, float **h, int row, int col, float b_frict,
+		float chezy);
+float t_visco(float v, float **h, int row, int col, float b_frict, float rho,
+		float visco, float ystress);
+float veldt(float ua, float t, float g_x, float p_x, float i_x, float t_x);
+float shift0(float **m, int r, int c, int maxR, int maxC, int minR, int minC, int n, int w);
+void out_print (float **matrix,char *name, int nr, int nc);
+void out_sum_print (float **matrix1,float **matrix2,float **matrix3,float **matrix4, char *name, int nr, int nc, int mode, float threshold);
+float nash_sutcliffe(float **m_t1,float**m_t2, int nr, int nc);
+void report_input(float ifrict,float rho,float ystress,float visco,float chezy,float bfrict,float fluid,float NS_thres,int t,int delta);

Added: grass-addons/grass7/grass7/raster/r.massmov/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,1122 @@
+/*****************************************************************************
+ *
+ * MODULE:	r.massmov
+ *
+ * AUTHOR(S):	Original author:
+ *              Santiago Begueria (EEAD-CSIC)
+ * 		Monia Molinari <monia.molinari supsi.ch>
+ * 		Massimiliano Cannata <massimiliano.cannata supsi.ch>
+ *		
+ *
+ * PURPOSE: This module is intended to provide the capability of simulating 
+ *          mass movement (fast landslide) over complex topography. This module
+ *          applies the Shallow Water Equation (SWE) with different types of 
+ *          rheologies (frictional,Voellmy,viscoplastic) 
+ *
+ *
+ * COPYRIGHT:	(C) 2012 by the GRASS Development Team
+ *
+ *		This program is free software under the GNU General Public
+ *		Licence (>=2). Read the file COPYING that cames with GRASS
+ *		for details.
+ *
+ ****************************************************************************/
+
+/* libraries*/
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "filters.h"
+#include "general_f.h"
+
+/* numerical stability control */
+#define CFLlimsup  0.5 			/* Higher value of the Courant-Friedrichs-Levy */
+#define CFLliminf  0.3			/* Lower value of the Courant-Friedrichs-Levy */
+#define MinNLoops  1 			  /* Minimum number of internal loops */
+#define MaxNLoops  124 			/* Maximum number of internal loops */
+#define InitialLoops  1  		/* Initial number of internal loops */
+#define laxfactor  0.5 			/* Low pass filtering for the lax function (0 = no filtering) */
+#define dTLeap  0.3 	   		/* Fraction of dT, used for time extrapolation of fluxes */
+#define verysmall  0.01 		/* threshold to avoid div by very small values */
+#define nullo -999.9f
+
+/* timestep control */
+#define dT 1.0              /* Timeslice */
+
+/* other constants */
+#define grav 9.8		        /* Gravity acceleration */
+
+/* functions definition  */
+#define min(A,B) ((A) < (B) ? (A):(B))
+#define max(A,B) ((A) > (B) ? (A):(B))
+
+/*
+ * global functions declaration
+ */
+
+/*
+ * main function
+ *
+ *
+ */
+
+int main(int argc, char *argv[]) {
+	struct Cell_head cellhd; /* it stores region information and header information of rasters */
+	struct Cell_head window;
+	struct History history; /*  holds meta-data */
+
+	/* mapset name locator */
+	char *mapset_ELEV;
+	char *mapset_HINI;
+	char *mapset_DIST;
+
+	/* input buffer */
+	FCELL *inrast_ELEV;
+	FCELL *inrast_HINI;
+	FCELL *inrast_DIST;
+
+	/* output buffer */
+	float *outrast_H;
+	float *outrast_V;
+
+	/* input file descriptor */
+	int infd_ELEV;
+	int infd_HINI;
+	int infd_DIST;
+
+	/* output file descriptor */
+	int outfd_H;
+	int outfd_V;
+
+	/* cell counters */
+	int row, col;
+	int nrows, ncols;
+	float res_ns, res_ew, ca;
+
+	/* input & output arguments */
+	int TIMESTEPS, DELTAT, RHEOL_TYPE;
+	float RHO, YSTRESS, CHEZY, VISCO, BFRICT, IFRICT, FLUID,NS_THRES;
+	char RHEOL;
+	char name1[20];
+	char *name_ELEV;
+	char *name_HINI;
+	char *name_DIST;
+	char *result_H;
+	char *result_V;
+	char *result_HMAX;
+	char *result_VMAX;
+
+	/* memory matrix */
+	float **m_ELEV, **m_HINI, **m_DIST;
+	int **m_OUTLET;
+	float **m_gx, **m_gy, **m_slope;
+	float **m_H, **m_Hloop_dt, **m_Hloop, **m_V, **m_Vloop, **m_Vloop_dt, **m_U,
+			**m_Uloop, **m_Uloop_dt, **m_HUloop, **m_HVloop, **m_Hold, **m_Hmax, **m_Vmax;
+	float **m_K, **m_Kloop, **m_Hland, **TEST;
+
+	/*int variables */
+
+	float elev_fcell_val, dist_fcell_val, hini_fcell_val;
+	int outlet_cell_val;
+
+	float gx, gy, slope;
+	float k_act, k_pas;
+	float G_x, G_y, I_x, I_y, P_x, P_y, T, T_x, T_y, T_x_b, T_y_b, T_b;
+	float ddt, dt;
+	float Uloop_a, Vloop_a, Uloop_b, Vloop_b, vel, vel_b, Uloop_dt, Vloop_dt, Hloop_a, Hloop_dt, dH_dT, H_fluid;
+	float CFL, CFL_u, CFL_v;
+	float Vol_gone_loop, Vol_exp_loop, mbe;
+	float NS,NSold;
+	int testPar;
+
+	/***********************************************************************************************************************/
+	/* GRASS structure */
+	struct GModule *module;
+	struct Option *input_ELEV, *input_HINI,*input_DIST,
+			*input_RHEOL, *input_RHO, *input_YSTRESS, *input_CHEZY,
+			*input_VISCO, *input_BFRICT, *input_IFRICT, *input_FLUID,
+			*input_TIMESTEPS, *input_DELTAT, *output_H, *output_VEL, *input_NS_THRES, *output_HMAX, *output_VMAX;
+	struct Flag *flag_i;
+
+	/* initialize GIS environment */
+	G_gisinit(argv[0]);
+
+	/* initialize module */
+	module = G_define_module();
+	G_add_keyword(_("raster"));
+	G_add_keyword(_("landslide"));
+	G_add_keyword(_("model"));
+	module->description =_("Estimation of run-out and deposition of landslide phenomena over a complex topography");
+
+	/* define the different options */
+
+	input_ELEV = G_define_option();
+	input_ELEV->key = "elev";
+	input_ELEV->type = TYPE_STRING;
+	input_ELEV->required = YES;
+	input_ELEV->gisprompt = "old,cell,raster";
+	input_ELEV->description = _("Name of elevation raster map");
+	input_ELEV->guisection = _("Input options");
+
+	input_HINI = G_define_option();
+	input_HINI->key = "h_ini";
+	input_HINI->type = TYPE_STRING;
+	input_HINI->required = YES;
+	input_HINI->gisprompt = "old,cell,raster";
+	input_HINI->description = _("Name of landslide initial body thickness raster map");
+	input_HINI->guisection = _("Input options");
+
+	input_DIST = G_define_option();
+	input_DIST->key = "fluiddist";
+	input_DIST->type = TYPE_STRING;
+	input_DIST->required = YES;
+	input_DIST->gisprompt = "old,cell,raster";
+	input_DIST->description = _("Name of distance from the landlide toe raster map");
+	input_DIST->guisection = _("Input options");
+
+	input_RHEOL = G_define_option();
+	input_RHEOL->key = "rheology";
+	input_RHEOL->type = TYPE_STRING;
+	input_RHEOL->required = YES;
+	input_RHEOL->options = "frictional,Voellmy,viscoplastic";
+	input_RHEOL->description = _("Name of rheological law");
+	input_RHEOL->guisection = _("Input options");
+
+	input_RHO = G_define_option();
+	input_RHO->key = "rho";
+	input_RHO->type = TYPE_DOUBLE;
+	input_RHO->required = NO;
+	input_RHO->multiple = NO;
+	input_RHO->description =_("Density of the flow [Kg/m3]. Required only for viscous rheologies.");
+	input_RHO->guisection = _("Input options");
+
+	input_YSTRESS = G_define_option();
+	input_YSTRESS->key = "ystress";
+	input_YSTRESS->type = TYPE_DOUBLE;
+	input_YSTRESS->required = NO;
+	input_YSTRESS->multiple = NO;
+	input_YSTRESS->description =_("Apparent yield stress [Pa]. Used only for viscous rheologies (optional).");
+	input_YSTRESS->guisection = _("Input options");
+
+	input_VISCO = G_define_option();
+	input_VISCO->key = "visco";
+	input_VISCO->type = TYPE_DOUBLE;
+	input_VISCO->required = NO;
+	input_VISCO->multiple = NO;
+	input_VISCO->description = _("Dynamic viscosity [Pa*s]. Required only for viscous rheologies");
+	input_VISCO->guisection = _("Input options");
+
+	input_CHEZY = G_define_option();
+	input_CHEZY->key = "chezy";
+	input_CHEZY->type = TYPE_DOUBLE;
+	input_CHEZY->required = NO;
+	input_CHEZY->multiple = NO;
+	input_CHEZY->description =_("Chezy roughness coefficient [m/s2]. Required only for Voellmy rheology");
+	input_CHEZY->guisection = _("Input options");
+
+	input_BFRICT = G_define_option();
+	input_BFRICT->key = "bfrict";
+	input_BFRICT->type = TYPE_DOUBLE;
+	input_BFRICT->required = NO;
+	input_BFRICT->multiple = NO;
+	input_BFRICT->description = _("Angle of basal friction [deg]");
+	input_BFRICT->guisection = _("Input options");
+
+	input_IFRICT = G_define_option();
+	input_IFRICT->key = "ifrict";
+	input_IFRICT->type = TYPE_DOUBLE;
+	input_IFRICT->required = YES;
+	input_IFRICT->multiple = NO;
+	input_IFRICT->description = _("Angle of internal friction [deg]");
+	input_IFRICT->guisection = _("Input options");
+
+	input_FLUID = G_define_option();
+	input_FLUID->key = "fluid";
+	input_FLUID->type = TYPE_DOUBLE;
+	input_FLUID->required = YES;
+	input_FLUID->multiple = NO;
+	input_FLUID->description = _("Upward velocity of transition from solid to fluid of the landsliding mass [m/s]");
+	input_FLUID->guisection = _("Input options");
+
+	input_TIMESTEPS = G_define_option();
+	input_TIMESTEPS->key = "timesteps";
+	input_TIMESTEPS->type = TYPE_INTEGER;
+	input_TIMESTEPS->required = YES;
+	input_TIMESTEPS->multiple = NO;
+	input_TIMESTEPS->description = _(
+			"Maximum number of time steps of the simulation [s]");
+	input_TIMESTEPS->guisection = _("Input options");
+
+	input_DELTAT = G_define_option();
+	input_DELTAT->key = "deltatime";
+	input_DELTAT->type = TYPE_INTEGER;
+	input_DELTAT->required = NO;
+	input_DELTAT->multiple = NO;
+	input_DELTAT->description = _("Reporting time frequency [s]");
+	input_DELTAT->guisection = _("Input options");
+
+	input_NS_THRES = G_define_option();
+	input_NS_THRES->key = "ns_thres";
+	input_NS_THRES->type = TYPE_DOUBLE;
+	input_NS_THRES->required = NO;
+	input_NS_THRES->multiple = NO;
+	input_NS_THRES->description = _("Threshold for Nash-Sutcliffe convergence [-]");
+	input_NS_THRES->guisection = _("Input options");
+
+	output_H = G_define_option();
+	output_H->key = "h";
+	output_H->type = TYPE_STRING;
+	output_H->required = NO;
+	output_H->gisprompt = "new,cell,raster";
+	output_H->description = _("Prefix for flow thickness output raster maps");
+	output_H->guisection = _("Output options");
+
+	output_HMAX = G_define_option();
+	output_HMAX->key = "h_max";
+	output_HMAX->type = TYPE_STRING;
+	output_HMAX->required = NO;
+	output_HMAX->gisprompt = "new,cell,raster";
+	output_HMAX->description = _("Prefix for maximum flow thickness output raster maps");
+	output_HMAX->guisection = _("Output options");
+
+	output_VEL = G_define_option();
+	output_VEL->key = "v";
+	output_VEL->type = TYPE_STRING;
+	output_VEL->required = NO;
+	output_VEL->gisprompt = "new,cell,raster";
+	output_VEL->description = _("Prefix for flow velocity output raster maps");
+	output_VEL->guisection = _("Output options");
+
+	output_VMAX = G_define_option();
+	output_VMAX->key = "v_max";
+	output_VMAX->type = TYPE_STRING;
+	output_VMAX->required = NO;
+	output_VMAX->gisprompt = "new,cell,raster";
+	output_VMAX->description = _("Prefix for maximum flow velocity output raster maps");
+	output_VMAX->guisection = _("Output options");
+
+    flag_i = G_define_flag();
+    flag_i->key = 'i';
+    flag_i->description = _("Print input data");
+
+	if (G_parser(argc, argv))
+		exit(EXIT_FAILURE);
+
+	/***********************************************************************************************************************/
+	/* get entered parameters */
+
+	name_ELEV = input_ELEV->answer;
+	name_DIST = input_DIST->answer;
+	name_HINI = input_HINI->answer;
+
+	result_H = output_H->answer;
+	result_V = output_VEL->answer;
+	result_HMAX = output_HMAX->answer;
+	result_VMAX = output_VMAX->answer;
+
+	G_debug(1,"Getting numeric input data...");
+
+	if (strcmp(input_RHEOL->answer, "frictional") == 0)
+		RHEOL_TYPE = 1;
+	if (strcmp(input_RHEOL->answer, "Voellmy") == 0)
+		RHEOL_TYPE = 2;
+	if (strcmp(input_RHEOL->answer, "viscoplastic") == 0)
+		RHEOL_TYPE = 3;
+
+
+	if (input_RHO->answer)
+		sscanf(input_RHO->answer, "%f", &RHO);
+	else
+		RHO = -1;
+
+	if (input_YSTRESS->answer)
+		sscanf(input_YSTRESS->answer, "%f", &YSTRESS);
+	else
+		YSTRESS = -1;
+
+	if (input_CHEZY->answer)
+		sscanf(input_CHEZY->answer, "%f", &CHEZY);
+	else
+		CHEZY = -1;
+	
+	if (input_VISCO->answer)
+		sscanf(input_VISCO->answer, "%f", &VISCO);
+	else
+		VISCO = -1;
+	
+	if (input_BFRICT->answer)
+		sscanf(input_BFRICT->answer, "%f", &BFRICT);
+	else
+		BFRICT = -1;
+
+	if (input_NS_THRES->answer)
+		sscanf(input_NS_THRES->answer, "%f", &NS_THRES);
+	else
+		NS_THRES = -1;
+
+	sscanf(input_IFRICT->answer, "%f", &IFRICT);
+
+	sscanf(input_FLUID->answer, "%f", &FLUID);
+
+	if (input_DELTAT->answer)
+		DELTAT = atoi(input_DELTAT->answer);
+	else
+		DELTAT = -1;
+
+	TIMESTEPS = atoi(input_TIMESTEPS->answer);
+
+	/* check outputs required */
+	if (!((result_H) || (result_V) || (result_HMAX) || (result_VMAX))){
+		G_fatal_error(_("No output specified"));
+	}
+	
+	/* check rheology parameters */
+	testPar = check_rheol_par(RHEOL_TYPE, CHEZY, VISCO, RHO);
+	
+	if (testPar == -2)
+		G_fatal_error(_("For the selected rheology Chezy parameter is required"));
+	
+	if (testPar == -3)
+		G_fatal_error(_("For the selected rheology viscosity and density parameters are required"));
+	
+	/* report Input Data */
+	if (flag_i->answer){
+		report_input(IFRICT,RHO, YSTRESS, VISCO, CHEZY, BFRICT,FLUID, NS_THRES, TIMESTEPS, DELTAT);
+	}
+
+	G_debug(2,"Verifiyng raster maps input data...");
+
+	/* find maps in mapset */
+	mapset_ELEV = (char *) G_find_raster2(name_ELEV, "");
+	if (mapset_ELEV == NULL)
+		G_fatal_error(_("cell file [%s] not found"), name_ELEV);
+
+	mapset_DIST = (char *) G_find_raster2(name_DIST, "");
+	if (mapset_DIST == NULL)
+		G_fatal_error(_("cell file [%s] not found"), name_DIST);
+
+	mapset_HINI = (char *) G_find_raster2(name_HINI, "");
+	if (mapset_HINI == NULL)
+		G_fatal_error(_("cell file [%s] not found"), name_HINI); 
+
+	/* rast_open_old */
+	if ((infd_ELEV = Rast_open_old(name_ELEV, mapset_ELEV)) < 0)
+		G_fatal_error(_("Cannot open cell file [%s]"), name_ELEV);
+
+
+	if ((infd_DIST = Rast_open_old(name_DIST, mapset_DIST)) < 0)
+		G_fatal_error(_("Cannot open cell file [%s]"), name_DIST);
+
+	if ((infd_HINI = Rast_open_old(name_HINI, mapset_HINI)) < 0)
+		G_fatal_error(_("Cannot open cell file [%s]"), name_HINI);
+
+
+	/* controlling if we can open input raster */
+	Rast_get_cellhd(name_ELEV, mapset_ELEV, &cellhd);
+	G_debug(3, "number of rows %d", cellhd.rows);
+
+	Rast_get_cellhd(name_DIST, mapset_DIST, &cellhd);
+	G_debug(3, "number of rows %d", cellhd.rows);
+
+	Rast_get_cellhd(name_HINI, mapset_HINI, &cellhd); 
+	G_debug(3, "number of rows %d", cellhd.rows);
+
+
+	/* allocate input buffer */
+	inrast_ELEV = Rast_allocate_f_buf(); 
+	inrast_DIST = Rast_allocate_f_buf();
+	inrast_HINI = Rast_allocate_f_buf();
+
+	G_debug(1,"Getting region extension...");
+
+	/* get windows rows & cols */
+	nrows = Rast_window_rows();
+	ncols = Rast_window_cols();
+	G_get_window(&window);
+	res_ew = window.ew_res;
+	res_ns = window.ns_res;
+	ca = res_ns * res_ew;
+
+
+	G_debug(2,"Allocating memory matrix...");
+
+	/* allocate memory matrix */
+	m_ELEV = G_alloc_fmatrix(nrows, ncols);
+	m_OUTLET = G_alloc_imatrix(nrows, ncols);
+	m_DIST = G_alloc_fmatrix(nrows, ncols);
+	m_HINI = G_alloc_fmatrix(nrows, ncols);
+	m_gx = G_alloc_fmatrix(nrows, ncols);
+	m_gy = G_alloc_fmatrix(nrows, ncols);
+	m_slope = G_alloc_fmatrix(nrows, ncols);
+	m_U = G_alloc_fmatrix(nrows, ncols);
+	m_Uloop = G_alloc_fmatrix(nrows, ncols);
+	m_Uloop_dt = G_alloc_fmatrix(nrows, ncols);
+	m_V = G_alloc_fmatrix(nrows, ncols);
+	m_Vloop = G_alloc_fmatrix(nrows, ncols);
+	m_Vloop_dt = G_alloc_fmatrix(nrows, ncols);
+	m_H = G_alloc_fmatrix(nrows, ncols);
+	m_Hloop = G_alloc_fmatrix(nrows, ncols);
+	m_Hloop_dt = G_alloc_fmatrix(nrows, ncols);
+	m_Hland = G_alloc_fmatrix(nrows, ncols);
+	m_K = G_alloc_fmatrix(nrows, ncols);
+	m_Kloop = G_alloc_fmatrix(nrows, ncols);
+	m_HUloop = G_alloc_fmatrix(nrows, ncols);
+	m_HVloop = G_alloc_fmatrix(nrows, ncols);
+
+	if (NS_THRES!=-1){
+		m_Hold= G_alloc_fmatrix(nrows, ncols);
+	}
+
+	if (result_HMAX){
+		m_Hmax = G_alloc_fmatrix(nrows, ncols);
+	}
+
+	if (result_VMAX){
+		m_Vmax = G_alloc_fmatrix(nrows, ncols);
+	}
+
+	/* read rows */
+	G_debug(2,"Reading input maps...");
+	for (row = 0; row < nrows; row++) {
+
+		/* read a line input maps into buffers*/
+		Rast_get_f_row(infd_ELEV, inrast_ELEV, row);
+		Rast_get_f_row(infd_DIST, inrast_DIST, row);
+		Rast_get_f_row(infd_HINI, inrast_HINI, row);
+
+		for (col = 0; col < ncols; col++) {
+			elev_fcell_val = ((FCELL *) inrast_ELEV)[col];
+			dist_fcell_val = ((FCELL *) inrast_DIST)[col];
+			hini_fcell_val = ((FCELL *) inrast_HINI)[col];
+
+			/* elevation map */
+			if (Rast_is_f_null_value(&elev_fcell_val) == 1) {
+				m_ELEV[row][col] = nullo;
+			} else {
+				m_ELEV[row][col] = ((FCELL *) inrast_ELEV)[col];
+			}
+
+			/* distance map */
+			if (Rast_is_f_null_value(&dist_fcell_val) == 1) {
+				m_DIST[row][col] = nullo;
+			} else {
+				m_DIST[row][col] = ((FCELL *) inrast_DIST)[col];
+			}
+
+			/* hini map */      
+			if (Rast_is_f_null_value(&hini_fcell_val) == 1) {
+				m_HINI[row][col] = nullo;
+			} else {
+				m_HINI[row][col] = ((FCELL *) inrast_HINI)[col];
+			}
+
+		}
+	}
+
+	/* memory cleanup */
+	G_free(inrast_ELEV);
+	G_free(inrast_DIST);
+	G_free(inrast_HINI);
+
+	/* closing raster map */
+	Rast_close(infd_ELEV);
+	Rast_close(infd_DIST);
+	Rast_close(infd_HINI);
+
+
+	/* earth pressure coefficient */
+	k_act = (1 - sin((M_PI * IFRICT) / 180.0))
+			/ (1 + sin((M_PI * IFRICT) / 180.0));
+
+	k_pas = (1 + sin((M_PI * IFRICT) / 180.0))
+			/ (1 - sin((M_PI * IFRICT) / 180.0));
+
+	G_debug(1,"K_pas value = %f",k_pas);
+	G_debug(1,"K_act value = %f",k_act);
+
+
+	/* inizializzazione matrici in memoria: U,V,H,gx,gz,slope */
+
+	for (row = 0; row < nrows; row++) {
+		for (col = 0; col < ncols; col++) {
+
+			m_H[row][col] = 0;
+			m_Hloop[row][col] = 0;
+			m_Hloop_dt[row][col] = 0;
+			m_Hland[row][col] = 0;
+			m_U[row][col] = 0;
+			m_Uloop[row][col] = 0;
+			m_Uloop_dt[row][col] = 0;
+			m_V[row][col] = 0;
+			m_Vloop[row][col] = 0;
+			m_Vloop_dt[row][col] = 0;
+			m_K[row][col] = nullo;
+			m_gx[row][col] = nullo;
+			m_gy[row][col] = nullo;
+			m_slope[row][col] = nullo;
+			m_HUloop[row][col] = 0;
+			m_HVloop[row][col] = 0;
+		}
+	}
+
+	for (row = 0; row < nrows; row++) {
+		for (col = 0; col < ncols; col++) {
+			if (row==0 || row==1 || col==0 || col==1 || row==nrows-1 || col==ncols-1 || row==nrows-2 || col==ncols-2)
+				m_OUTLET[row][col]=1;
+			else
+				m_OUTLET[row][col]=0;
+		}
+	}
+
+
+	if (NS_THRES!=-1){
+		for (row = 0; row < nrows; row++) {
+			for (col = 0; col < ncols; col++) {
+				m_Hold[row][col] = 0;
+			}
+		}
+	}
+
+
+	if (result_HMAX){
+		for (row = 0; row < nrows; row++) {
+			for (col = 0; col < ncols; col++) {
+				m_Hmax[row][col] = 0;
+			}
+		}
+	}
+
+	if (result_VMAX){
+		for (row = 0; row < nrows; row++) {
+			for (col = 0; col < ncols; col++) {
+				m_Vmax[row][col] = 0;
+			}
+		}
+	}
+
+
+
+   /*---------------------------------------------------------- */
+   /* calcolo matrici gx, gy, slope */
+
+	for (row = 1; row < nrows - 1; row++) {
+		for (col = 1; col < ncols - 1; col++) {
+
+			gx = gradx2(m_ELEV, row, col, res_ew, 0);
+			gy = grady2(m_ELEV, row, col, res_ns, 0);
+
+			/* slope calcolata con Horn 3x3 */
+			slope = sqrt(pow(gradx3(m_ELEV, row, col, res_ew, 0), 2) + pow(grady3(m_ELEV, row, col, res_ns, 0), 2));
+			m_gx[row][col] = gx;
+			m_gy[row][col] = gy;
+			m_slope[row][col] = slope;
+
+		}
+	}
+
+
+	/* Starting loops*/
+	int t=1;
+	int i;
+	int loop, n_loops = 1;
+	float incr_volexp = 0;
+	float Vol_gone=0;
+	float Vol_exp=0;
+	float Vol_actual=0;
+	int NS_count = 0;
+
+
+	/* while: for each timestep or until NS_count<3 */
+    while (NS_count<3 && t<=TIMESTEPS) {
+		i = t - 1;
+
+		float CFL_max = 0;
+		int stable = 0;
+
+		for (row = 1; row < nrows - 1; row++) {
+			for (col = 1; col < ncols - 1; col++) {
+
+				/* Ricalcolo H in funzione di H_fluid e calcolo incremento di Volume aspettato */
+				if (m_DIST[row][col] <= i * dT * FLUID
+						&& m_DIST[row][col] > (i - 1) * dT * FLUID) {
+					H_fluid = m_HINI[row][col];
+					m_H[row][col] += H_fluid;
+				} else {
+					H_fluid = 0.0;
+				}
+				incr_volexp += H_fluid/(cos(atan(m_slope[row][col])))*ca;
+
+
+				/* Calcolo Hland */
+				if (m_DIST[row][col] > i * dT * FLUID) {
+					m_Hland[row][col] = m_HINI[row][col];
+				} else {
+					m_Hland[row][col] = 0.0;
+				}
+			}
+		}
+
+		G_debug(1,"\nTIMESTEP %i",t);
+		G_debug(1,"Volume expected increment = %f",incr_volexp);
+
+		/* ciclo while */
+		while (stable==0) {
+			int exit = 0;
+
+
+			G_debug(2,"Updating maps and volumes");
+
+			/* Aggiornamento Hloop,Vloop e Uloop */
+			for (row = 1; row < nrows - 1; row++) {
+				for (col = 1; col < ncols - 1; col++) {
+					m_Hloop[row][col] = m_H[row][col];
+					m_Uloop[row][col] = m_U[row][col];
+					m_Vloop[row][col] = m_V[row][col];
+				}
+			}
+
+			/* Aggiornamento Volumi */
+			Vol_gone_loop = Vol_gone;
+			Vol_exp_loop = Vol_exp;
+			Vol_actual = 0;
+
+
+			/* Per ogni iterazione */
+			G_debug(1,"\n---NLOOPS=%i---",n_loops);
+			for (loop = 1; loop <= n_loops && exit == 0; loop++) {
+				G_debug(1,"\n-LOOP=%i",loop);
+
+
+				G_debug(2,"Updating K and Kloop matrix");
+
+				for (row = 1; row < nrows - 1; row++) {
+					for (col = 1; col < ncols - 1; col++) {
+						if ((gradx2(m_Uloop, row, col, res_ew, 0)
+								+ grady2(m_Vloop, row, col, res_ns, 0)) >= 0)
+							m_K[row][col] = k_act;
+						else
+							m_K[row][col] = k_pas;
+					}
+				}
+
+
+				for (row = 1; row < nrows - 1; row++) {
+					for (col = 1; col < ncols - 1; col++) {
+						m_Kloop[row][col] = lax(m_K, row, col, laxfactor);
+					}
+				}
+
+
+				/* ciclo row-col per calcolare G, P, I, T, Tb */
+				G_debug(2,"Calculating G, P, I, T, Tb");
+
+				for (row = 1; row < nrows - 1 && exit == 0; row++) {
+					for (col = 1; col < ncols - 1 && exit == 0; col++) {
+
+						/* Calcolo G_x e G_y */
+
+						if (m_Hloop[row][col] > verysmall) {
+							G_x = -grav * (sin(atan(m_gx[row][col])));
+						} else {
+							G_x = 0.0;
+						}
+
+
+						if (m_Hloop[row][col] > verysmall) {
+							G_y = -grav * (sin(atan(m_gy[row][col])));
+						} else {
+							G_y = 0.0;
+						}
+
+
+						/* Calcolo I_x e I_y */
+
+						I_x = -((m_Uloop[row][col] * (cos(atan(m_gx[row][col])))
+								* gradx2(m_Uloop, row, col, res_ew, 1))
+								+ (m_Vloop[row][col] * (cos(atan(m_gy[row][col])))
+										* grady2(m_Uloop, row, col, res_ew, 1)));
+
+						I_y = -((m_Uloop[row][col] * (cos(atan(m_gx[row][col])))
+								* gradx2(m_Vloop, row, col, res_ew, 1))
+								+ (m_Vloop[row][col] * (cos(atan(m_gy[row][col])))
+										* grady2(m_Vloop, row, col, res_ns, 1)));
+
+
+						/* Calcolo P_x e P_y */
+
+						if (m_Hloop[row][col] > verysmall) {
+							P_x = -m_Kloop[row][col] * cos(atan(m_gx[row][col]))
+									* gradPx2(m_Hloop, m_Hland, m_gx, row, col,
+											res_ew);
+						} else {
+							P_x = 0.0;
+						}
+
+						if (m_Hloop[row][col] > verysmall) {
+							P_y = -m_Kloop[row][col] * cos(atan(m_gy[row][col]))
+									* gradPy2(m_Hloop, m_Hland, m_gy, row, col,
+											res_ns);
+						} else {
+							P_y = 0.0;
+						}
+
+
+						/* Calcolo T_x e T_y */
+
+						vel = sqrt(
+								pow(m_Uloop[row][col], 2)
+										+ pow(m_Vloop[row][col], 2));
+
+
+						if (RHEOL_TYPE == 1) {
+							T = t_frict(m_Hloop, row, col, BFRICT);
+						}
+
+						if (RHEOL_TYPE == 2) {
+							T = t_voellmy(vel, m_Hloop, row, col, BFRICT, CHEZY);
+						}
+
+						if (RHEOL_TYPE == 3) {
+							T = t_visco(vel, m_Hloop, row, col, BFRICT, RHO, VISCO,
+									YSTRESS);
+						}
+
+						if (m_Hloop[row][col] > verysmall && vel > verysmall) {
+							T_x = fabs(m_Uloop[row][col]) / vel * grav
+									* (cos(atan(m_gx[row][col]))) * T;
+							T_y = fabs(m_Vloop[row][col]) / vel * grav
+									* (cos(atan(m_gy[row][col]))) * T;
+						}
+
+						else {
+							T_x = grav * (cos(atan(m_gx[row][col]))) * T;
+							T_y = grav * (cos(atan(m_gy[row][col]))) * T;
+						}
+
+
+						/* Stima del flusso a t + ddt */
+						ddt = dTLeap * dT / n_loops;
+
+						/* Lax su Uloop e Vloop se is_df altrimenti 0 */
+
+						Uloop_a = filter_lax(m_Uloop, row, col, laxfactor, m_Hloop, 0.01, 0.0);
+						Vloop_a = filter_lax(m_Vloop, row, col, laxfactor, m_Hloop, 0.01, 0.0);
+
+						/* Calcolo U_loop_b e V_loop_b */
+
+						Uloop_b = veldt(Uloop_a, ddt, G_x, P_x, I_x, T_x);
+						Vloop_b = veldt(Vloop_a, ddt, G_y, P_y, I_y, T_y);
+
+
+						/* Calcolo T_x_b, T_y_b in funzione delle nuove Uloop_b, Vloop_b */
+
+						vel_b = sqrt(pow(Uloop_b, 2) + pow(Vloop_b, 2));
+
+
+						if (RHEOL_TYPE == 1) {
+							T_b = T;
+						}
+
+						if (RHEOL_TYPE == 2) {
+							T_b = t_voellmy(vel_b, m_Hloop, row, col, BFRICT,
+									CHEZY);
+						}
+
+						if (RHEOL_TYPE == 3) {
+							T_b = t_visco(vel_b, m_Hloop, row, col, BFRICT, RHO,
+									VISCO, YSTRESS);
+						}
+
+
+						if (m_Hloop[row][col] > verysmall && vel_b > verysmall) {
+							T_x_b = fabs(Uloop_b) / vel_b * grav
+									* (cos(atan(m_gx[row][col]))) * T_b;
+							T_y_b = fabs(Vloop_b) / vel_b * grav
+									* (cos(atan(m_gy[row][col]))) * T_b;
+						} else {
+							T_x_b = grav * (cos(atan(m_gx[row][col]))) * T_b;
+							T_y_b = grav * (cos(atan(m_gy[row][col]))) * T_b;
+						}
+
+
+						/* Stima del flusso a t + dt*/
+
+						dt = dT / n_loops;
+						Uloop_dt = veldt(Uloop_a, dt, G_x, P_x, I_x, T_x_b);
+						Vloop_dt = veldt(Vloop_a, dt, G_y, P_y, I_y, T_y_b);
+
+						/* Calcolo del valore Courant-Friendrichs-Levy */
+
+						CFL_u = dt * sqrt(2)
+								* fabs((cos(atan(m_gx[row][col]))) * Uloop_dt)
+								/ res_ew;
+
+						CFL_v = dt * sqrt(2)
+								* fabs((cos(atan(m_gy[row][col]))) * Vloop_dt)
+								/ res_ns;
+
+						CFL = max(CFL_u,CFL_v);
+
+
+						if (CFL > CFL_max)
+							CFL_max = CFL;
+
+						/*	Verifica della condizione di stabilità */
+
+						if (CFL_max > CFLlimsup && n_loops < MaxNLoops) {
+							exit = 1;
+							n_loops += 1;
+							CFL_max=0;
+						} else {
+							m_Uloop_dt[row][col] = Uloop_dt;
+							m_Vloop_dt[row][col] = Vloop_dt;
+
+
+							if (m_Hloop[row][col] > verysmall) {
+								m_HUloop[row][col] = m_Hloop[row][col] * Uloop_dt;
+								m_HVloop[row][col] = m_Hloop[row][col] * Vloop_dt;
+							} else {
+								m_HUloop[row][col] = 0.0;
+								m_HVloop[row][col] = 0.0;
+							}
+						}
+					} /*chiusura FOR cols*/
+				} /*chiusura FOR rows*/
+
+				G_debug(2,"CFL_max=%f",CFL_max);
+
+				if (exit==0) {
+					G_debug(2,"Calculating Hloop_dt without mbe for loop");
+
+					for (row = 1; row < nrows - 1 && exit == 0; row++) {
+						for (col = 1; col < ncols - 1 && exit == 0; col++) {
+
+							/* calcolo dH/dT */
+							dH_dT = -cos(atan(m_gx[row][col]))* (shift0(m_HUloop,row,col,nrows-1,ncols-1,1,1,0,-1)-shift0(m_HUloop,row,col,nrows-1,ncols-1,1,1,0,1))/(2*res_ew/cos(atan(m_gx[row][col])))
+									-cos(atan(m_gy[row][col]))* (shift0(m_HVloop,row,col,nrows-1,ncols-1,1,1,1,0)-shift0(m_HVloop,row,col,nrows-1,ncols-1,1,1,-1,0))/(2*res_ns/cos(atan(m_gy[row][col])));
+
+							/* Lax su Hloop e calcolo Hloop_dt (senza mbe) */
+
+							if (dH_dT==0) {
+								Hloop_a=m_Hloop[row][col];
+							} else {
+								Hloop_a = filter_lax(m_Hloop, row, col, laxfactor, m_Hloop, 0.01, 0.0);
+							}
+
+							Hloop_dt = Hloop_a - dT/n_loops * dH_dT;
+
+
+							/* Vol_gone_loop */
+							Vol_actual += Hloop_dt/(cos(atan(m_slope[row][col])))*ca;
+							if (m_OUTLET[row][col]==1){
+								/*Vol_gone_no_mbe = Hloop_dt/(cos(atan(m_slope[row][col])))*ca;*/
+								Vol_gone_loop += Hloop_dt/(cos(atan(m_slope[row][col])))*ca;
+								Hloop_dt = 0.0;
+							}
+
+							/* matrice H_loop_dtemp */
+							m_Hloop_dt[row][col] = Hloop_dt;
+
+						}/*chiusura FOR col*/
+					}/*chiusura FOR row*/
+
+
+					/* m.b.e */
+					G_debug(2,"Calculating mass balance error");
+
+					Vol_exp_loop += incr_volexp/n_loops;
+
+					if (Vol_exp_loop > 0.01) {
+						mbe = Vol_actual/Vol_exp_loop;
+					} else {
+						mbe = 1;
+					}
+
+					G_debug(2,"mbe=%f",mbe);
+					
+					/*Vol_gone_loop += Vol_gone_no_mbe/mbe;*/
+					Vol_actual = 0;
+
+					/* Hloop_dt con mbe */
+					G_debug(2,"Calculating Hloop_dt with mbe for loop");
+
+					for (row = 1; row < nrows - 1 && exit == 0; row++) {
+						for (col = 1; col < ncols - 1 && exit == 0; col++) {
+							if (mbe > 0.01){
+								m_Hloop_dt[row][col]=m_Hloop_dt[row][col]/mbe;
+							}
+						}
+					}
+
+					/* loop<n_loops */
+					if (loop<n_loops) {
+						G_debug(2,"loop<n_loops");
+
+						for (row = 1; row < nrows - 1 && exit == 0; row++) {
+							for (col = 1; col < ncols - 1 && exit == 0; col++) {
+								m_Hloop[row][col]=m_Hloop_dt[row][col];
+								m_Uloop[row][col]=m_Uloop_dt[row][col];
+								m_Vloop[row][col]=m_Vloop_dt[row][col];
+							}
+						}
+					}
+
+				}/* chiusura IF exit*/
+
+			} /*chiusura FOR loops*/
+
+			if (exit==0) {
+				G_debug(2,"FINISH N_LOOPS");
+
+
+				/*------Nash-Sutcliffe-------*/
+				if (NS_THRES!=-1){
+					G_debug(1,"Calculating Nash-Sutcliffe value");
+					if (t==1){
+						NSold = nash_sutcliffe(m_Hold,m_Hloop_dt,nrows, ncols);
+					} else {
+						NS = nash_sutcliffe(m_Hold,m_Hloop_dt, nrows, ncols);
+						G_debug(1,"NS old value=%f",NSold);
+						G_debug(1,"NS value=%f",NS);
+
+						if(fabs(NS-NSold) <= NS_THRES){
+							NS_count += 1;
+						} else {
+							NS_count = 0;
+						}
+						NSold = NS;
+					}
+					G_debug(1,"NS count=%i",NS_count);
+				}
+				
+				for (row = 1; row < nrows - 1; row++) {
+					for (col = 1; col < ncols - 1; col++) {
+						m_H[row][col]=m_Hloop_dt[row][col];
+						m_U[row][col]=m_Uloop_dt[row][col];
+						m_V[row][col]=m_Vloop_dt[row][col];
+						if (NS_THRES!=-1){
+							m_Hold[row][col]=m_Hloop_dt[row][col];
+						}
+					}
+				}
+
+				if (result_HMAX){
+					for (row = 1; row < nrows - 1; row++) {
+						for (col = 1; col < ncols - 1; col++) {
+							if(m_H[row][col]+m_Hland[row][col] > m_Hmax[row][col])
+								m_Hmax[row][col] = m_H[row][col]+m_Hland[row][col];
+						}
+					}
+				}
+
+				if (result_VMAX){
+					for (row = 1; row < nrows - 1; row++) {
+						for (col = 1; col < ncols - 1; col++) {
+							if (m_H[row][col]>verysmall){
+								if ((sqrt(pow(m_U[row][col],2)+pow(m_V[row][col],2)))>m_Vmax[row][col]){
+									m_Vmax[row][col]=(sqrt(pow(m_U[row][col],2)+pow(m_V[row][col],2)));
+								}
+							}
+						}
+					}
+				}
+
+				stable=1;
+				G_debug(1,"Vol_gone_loop=%f\n",Vol_gone_loop);
+
+
+				Vol_exp=Vol_exp_loop;
+				Vol_gone=Vol_gone_loop;
+
+				incr_volexp=0.0;
+				if (CFL_max<=CFLliminf) {
+					n_loops=max(n_loops-1,MinNLoops);
+				}
+
+				/*------- DEFAULT OUTPUT SERIES--------*/
+
+				if((DELTAT!=-1 && t%DELTAT==0) || (t==TIMESTEPS) || (NS_count==3)){
+
+					if(result_H){
+						sprintf(name1,"%s_t%d",result_H,t);
+						out_sum_print(m_Hland,m_H,m_U,m_V,name1,nrows,ncols,1,0.01);
+						Rast_short_history(name1, "raster", &history);
+						Rast_command_history(&history);
+						Rast_write_history(name1, &history);
+					}
+					if(result_V){
+						sprintf(name1,"%s_t%d",result_V,t);
+						out_sum_print(m_Hland,m_H,m_U,m_V,name1,nrows,ncols,2,0.01);
+						Rast_short_history(name1, "raster", &history);
+						Rast_command_history(&history);
+						Rast_write_history(name1, &history);
+					}
+				}
+
+
+				if((result_HMAX) && ((t==TIMESTEPS) || (NS_count==3))){
+					sprintf(name1,"%s",result_HMAX);
+					out_print(m_Hmax,name1,nrows,ncols);
+					Rast_short_history(name1, "raster", &history);
+					Rast_command_history(&history);
+					Rast_write_history(name1, &history);
+				}
+
+				if((result_VMAX) && ((t==TIMESTEPS) || (NS_count==3))){
+					sprintf(name1,"%s",result_VMAX);
+					out_print(m_Vmax,name1,nrows,ncols);
+					Rast_short_history(name1, "raster", &history);
+					Rast_command_history(&history);
+					Rast_write_history(name1, &history);
+				}
+
+
+			} /*chiusura IF exit*/
+		} /*chiusura WHILE*/
+		t++;
+	} /* chiusura WHILE NS_count*/
+
+	if (Vol_gone>0){
+		G_warning("The flow is out of the current computational domain. You may need to change the region extension.");
+		G_warning("Volume gone: %f",Vol_gone);
+	}
+
+
+	/* deallocate memory matrix */
+	G_free_fmatrix(m_ELEV);
+	G_free_imatrix(m_OUTLET);
+	G_free_fmatrix(m_DIST);
+	G_free_fmatrix(m_HINI);
+	G_free_fmatrix(m_gx);
+	G_free_fmatrix(m_gy);
+	G_free_fmatrix(m_slope);
+	G_free_fmatrix(m_H);
+	G_free_fmatrix(m_Hloop);
+	G_free_fmatrix(m_Hloop_dt);
+	G_free_fmatrix(m_Hland);
+	G_free_fmatrix(m_U);
+	G_free_fmatrix(m_Uloop);
+	G_free_fmatrix(m_Uloop_dt);
+	G_free_fmatrix(m_V);
+	G_free_fmatrix(m_Vloop);
+	G_free_fmatrix(m_Vloop_dt);
+	G_free_fmatrix(m_K);
+	G_free_fmatrix(m_Kloop);
+	G_free_fmatrix(m_HUloop);
+	G_free_fmatrix(m_HVloop);
+
+	if (NS_THRES!=-1)
+		G_free_fmatrix(m_Hold);
+
+	if (result_VMAX)
+		G_free_fmatrix(m_Vmax);
+
+	if (result_HMAX)
+		G_free_fmatrix(m_Hmax);
+		
+	exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.massmov/r.massmov.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.massmov/r.massmov.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.massmov/r.massmov.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,81 @@
+<h2>DESCRIPTION</h2>
+
+MassMov2D is a numerical model that allows users to simulate the expansion (runout)
+and deposition of mass movements over a complex topography by approximating the
+heterogeneous sliding mass to a homogeneous one-phase fluid (following the approach
+proposed by Savage and Hutter (1989) and Iverson and Denlinger (2001).
+The model describes the mass movements as a two-dimensional flux taking advantage
+of the shallow water equations. This formula is derived from the general Navier-
+Stokes equations under the hypothesis that the vertical components of velocity and
+pressure are negligible with respect to the horizontal components, and that the vertical
+pressure profile can be considered as almost hydrostatic (Kinnmark 1985).
+
+<p>
+The required inputs can be classified in three categories based on the information type:
+<ul>
+<li> raster maps of the topography, in particular the sliding surface topography (digital terrain
+model without the sliding body), the initial sliding mass thickness and the 'distance map',
+representing the cells distance from the collapsing body lower limit;</li>
+<li> numerical parameters for the characterization of the mass material, density [kg/m3], apparent
+yield stress [Pa], Chezy roughness coefficient [m/s2], dynamic viscosity [Pa*s], basal friction
+angle [deg], internal friction angle of the sliding mass during the expansion [deg] and the fluid rate [m/s].This last parameter provides information on the transaction velocity of the
+sliding mass when passes from a solid state to a fluid state; together with the 'distance map'
+it allows to define the amount of mass mobilized as a function of time. It is worth noting that
+depending on the selected rheological law different sets of parameters are mandatory;</li>
+<li>control parameters that are used to stop the simulation, like maximum time step number and/or Nash-Sutcliff tresholds value.</li>
+</ul>
+
+The model outputs a series of flux velocity map and deposit depth raster map at different time step according to the setted <i>deltatime</i> parameter; Additionally the module outputs two raster maps representing the maximum thickness and velocity registered during the simulation.
+
+<h2>NOTES</h2>
+The generation of the model input maps, in case the simulation refer to en existing collapse and pre and post event DTM is available, can be performed taking advantage of the GRASS modules; in
+particular:
+
+<ul>
+<li>the sliding surface can be calculated by subtracting the collapsing body from the pre-event
+DTM (r.mapcalc) </li>
+<li>the collapsing body thickness can  evaluated by considering the negative differences between
+the post and pre-event DTM multiplied for the cosine of the slope (r.mapcalc and
+r.slope.aspect)</li>
+<li>the distance map from the landslide toe can be obtained by applying the r.grow.distance module to the rasterized limits of the landslide</li>
+</ul>
+
+<h2>DIAGNOSTICS</h2>
+The module has been tested in several cases (see references), but up to now most of the simulations was done using a Voellmy rheology thus other rheology laws should be better investigated.
+
+
+<h2>REFERENCES</h2>
+<ul>
+<li>Savage S B and Hutter K 1989 The motion of a finite mass of granular material down a rough
+incline. Journal of Fluid Mechanics 199:177-215</li>
+
+<li>Iverson R M and Denlinger R P 2001 Flow of variably fluidized granular masses across 
+threedimensional terrain: 1, Coulomb mixture theory. Journal of Geophysical Research 106:537-52</li>
+
+<li>Kinnmark I P E 1985 The shallow water equations: Formulation, analysis and application. In
+Brebia C A and Orszag S A (eds) Lecture Notes in Engineering 15. Berlin, Springer-Verlag:1-187</li>
+
+<li>Begueria S, Van Asch T W J, Malet J P and Grondahl S 2009 A GIS based numerical model for simulating the kinematics 
+of mud and debris flows over complex terrain. Nat Hazards Earth Syst Sci, 9, 1897-1909.</li>
+
+<li>Molinari M, Cannata M, Begueria S and Ambrosi C 2012 GIS-based Calibration of MassMov2D. 
+Transactions in GIS, 2012, 16(2):215-231</li>
+</ul>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.grow.distance.html">r.grow.distance</a>,
+<a href="r.slope.aspect.html">r.slope.aspect</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>
+</em>
+
+<h2>AUTHORS</h2>
+
+<p><i>Original version of program:</i>
+<br>Santiago Begueria
+
+<p><i>The current version of the program (ported to GRASS7.0)</i>:
+<br>Monia Molinari, Massimiliano Cannata, Santiago Begueria.<br>
+
+<p><i>Last changed: $Date: 2012-06-02 09:28:14 +0200 (Sat, 02 Jun 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.mess/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.mess/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.mess/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.mess
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script

Added: grass-addons/grass7/grass7/raster/r.mess/r.mess
===================================================================
--- grass-addons/grass7/grass7/raster/r.mess/r.mess	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.mess/r.mess	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,349 @@
+#!/bin/sh
+# 
+########################################################################
+# 
+# MODULE:       r.mess
+# AUTHOR(S):    Paulo van Breugel <p.vanbreugel AT gmail.com>
+# PURPOSE:      Calculate the multivariate environmental similarity 
+#               surface (MESS) as proposed by Elith et al., 2010, 
+#               Methods in Ecology & Evolution, 1(330–342). 
+#
+# NOTES:        This GRASS script should give results very close (but
+#               due to rounding differences probably not exactly the 
+#               same) to those calculated in Maxent. However, note that
+#               Maxent uses, as far as I understand, the background 
+#               points. Therefore, if you want to compare the MESS layer 
+#               as calculated by Maxent with the results of this script
+#               you need to make sure to use the same points as input
+#
+# Disclaimer:   I use it in my work, but I am aware that it needs
+#               improvements. Suggestions for improvements are most
+#               welcome. In the meantime, use it at your own risk
+#   
+# COPYRIGHT: (C) 2012 Paulo van Breugel
+#            http://ecodiv.org
+#            http://pvanb.wordpress.com/
+# 
+#            This program is free software under the GNU General Public 
+#            License (>=v2). Read the file COPYING that comes with GRASS 
+#            for details. 
+# 
+########################################################################
+#
+#%Module 
+#% description: Computes multivariate environmental similarity surface
+#%End 
+
+#%option
+#% key: vector_input
+#% type: string
+#% gisprompt: old,vector
+#% description: Reference points
+#% key_desc: name
+#% required: yes
+#% multiple: no
+#%end
+
+#%option
+#% key: raster_input
+#% type: string
+#% gisprompt: old,cell,raster
+#% description: Input raster map(s) 
+#% key_desc: names
+#% required: yes
+#% multiple: yes
+#%end
+
+#%option
+#% key: output
+#% type: string
+#% gisprompt: new
+#% description: Root name of the output MESS data layers
+#% key_desc: name
+#% required: yes
+#%end
+
+#%option
+#% key: columns
+#% type: string
+#% description: Columns with environmental variables
+#% key_desc: string
+#% answer: Same names as input layers
+#% required: no
+#%end
+
+##%flag
+##% key: n
+##% description: Keep individual environmental dissimilarity layers (IED)
+##%end
+
+#%flag
+#% key: m
+#% description: Most dissimilar variable (MoD)
+#%end
+
+#%flag
+#% key: k
+#% description: Calculate MESS_mean
+#%end
+
+#%flag
+#% key: l
+#% description: Calculate MESS_median
+#%end
+
+#=======================================================================
+## GRASS team recommandations
+#=======================================================================
+
+## Check if in GRASS
+if  [ -z "$GISBASE" ] ; then
+    echo "You must be in GRASS GIS to run this program." 1>&2
+    exit 1
+fi
+
+## check for awk
+if [ ! -x "$(which awk)" ] ; then
+    g.message -e "<awk> required, please install <awk> or <gawk> first"
+    exit 1
+fi
+
+## To parse the code into interactive menu
+if [ "$1" != "@ARGS_PARSED@" ] ; then
+    exec g.parser "$0" "$@"
+fi
+
+## set environment so that awk works properly in all languages ##
+unset LC_ALL
+export LC_NUMERIC=C
+
+
+## what to do in case of user break:
+exitprocedure()
+{
+    echo "User break!"
+    cleanup
+    exit 1
+}
+
+## shell check for user break (signal list: trap -l)
+trap "exitprocedure" 2 3 15
+
+#=======================================================================
+## testing if output maps already exist
+#=======================================================================
+
+## Set easier variable names
+OUTMAPS="${GIS_OPT_OUTPUT}"
+INMAPS="${GIS_OPT_RASTER_INPUT}"
+
+# test for output raster map
+g.findfile element=cell file=${OUTMAPS}_combined  > /dev/null
+    if [ $? -eq 0 ] ; then
+        g.message -e 'There is already a raster <${OUTMAPS}>'
+    exit 1
+fi
+
+# test for output raster maps
+oIFS=$IFS
+IFS=,
+for nvar in $INMAPS ; do
+    arrIN=${OUTMAPS}_`echo $nvar | awk 'BEGIN{FS="@"}{print $1}'`
+    g.findfile element=cell file=${arrIN} > /dev/null
+    if [ $? -eq 0 ] ; then 
+        g.message -e 'There is already a raster <${OUTMAPS}>'
+    exit 1
+    fi
+done
+IFS=$oIFS
+unset arrIN
+
+#=======================================================================
+## Config and general procedures
+#=======================================================================
+
+##fix this path
+if [ -z "$PROCESSDIR" ] ; then
+	PROCESSDIR="$HOME"
+fi
+
+#fix this path
+if [ -z "$LOGDIR" ] ; then
+	LOGDIR="$HOME"
+fi
+LOGFILE="$LOGDIR/r.mess.log"
+
+echo "r.mess :" >> "$LOGFILE"
+
+#=======================================================================
+## Preparing input variables for use in R script
+#=======================================================================
+
+# Create vectors with names output maps [arrOUT]
+# Create vector with names temporary layers [tmpLY]
+# Create vector with names input layers without mapset name [arrIN]
+# The 'removeThis' elements are to initiate the vector. How can I avoid this?
+
+arrOUT="${OUTMAPS}_MESS"
+tmpLY="removeThis"
+arrIN="removeThis2"
+counter=0
+IFS=,
+for nvar in ${INMAPS} ; do
+    arrOUT="$arrOUT;${OUTMAPS}_`echo $nvar | awk 'BEGIN{FS="@"}{print $1}'`"
+    counter=`expr $counter + 1`
+    tmpLY="${tmpLY};tmp.mess_$$_$counter"
+    arrIN="${arrIN};`echo $nvar | awk 'BEGIN{FS="@"}{print $1}'`"
+done
+
+#=======================================================================
+## Creating the R script
+#=======================================================================
+
+writeScript(){ 
+cat > $1 << "EOF"
+
+options(echo = FALSE)
+require(spgrass6)
+
+## Get vector with variables
+args <- commandArgs(trailingOnly=TRUE)
+ipn <- unlist(strsplit(args[1],";"))[-1]   # variable names
+ipl <- unlist(strsplit(args[2],","))       # environmental layers
+opl <- unlist(strsplit(args[3],";"))       # output layers
+opi <- opl[-1]                             # base name individual layers
+opc <- opl[1]                              # name of MESS layer
+tml <- unlist(strsplit(args[4], ";"))[-1]  # temporary layers
+vtl <- args[5]                             # vector layer
+cln <- args[6]
+
+# Import the vector point layer
+spl <- readVECT6(vtl)
+
+# Extract columns and create table
+# Use column names if given, otherwise,
+# use names input layers (ipl)
+if(cln == "Same names as input layers"){
+    spld <- spl at data[,ipn]
+}else{
+    cln <- unlist(strsplit(cln,","))
+    spld <- spl at data
+    spld <- spld[,cln]
+    }
+
+#-----------------------------------------------------------------------
+
+# Create the r.mapcalc expressions to calculate the mess for the 
+# individual layers. The main step is to define the graph function to 
+# be used (check out: possible alternative would be to use reclass)
+if(is.null(dim(spld))){
+    minp <- min(spld)
+    maxp <- max(spld)
+}else{
+    minp <- apply(spld, 2, min)
+    maxp <- apply(spld, 2, max)
+}
+
+for(i in 1:length(ipl)){
+    envir <- system(paste("r.univar -t map=", ipl[i], " fs=,", sep=""), intern=TRUE)
+    envir <- as.numeric(unlist(strsplit(envir[2], split=",")))
+    envmax <- ifelse(envir[4]==maxp[i],maxp[i]+(maxp[i]-minp[i])*0.001,envir[4])
+    envmin <- ifelse(envir[3]==minp[i],minp[i]-(maxp[i]-minp[i])*0.001,envir[3])
+    if(is.null(dim(spld))){
+        a  <- table(spld)
+    }else{a  <- table(spld[,i])
+    }
+    x1 <- as.numeric(rownames(a))
+    x2 <- c(x1[-1],envmax)
+    x3 <- x1 + (x2-x1)/1000
+    a1 <- paste(envmin, paste(x1,x3,sep=",", collapse=","), envmax, sep=",")
+    b  <- round(cumsum(as.numeric(a))/sum(a)*100,3)
+    a2 <- paste(0, 0, paste(b, b, sep=",", collapse=","), sep=",")
+    a3 <- paste(strsplit(a1,",")[[1]],strsplit(a2,",")[[1]],sep=",", collapse=",")
+    
+    system(paste("r.mapcalc '", tml[i], " = graph(", ipl[i], ",", a3, ")'", sep=""))
+    system(paste("r.mapcalc '", opi[i], " = if(", tml[i], "==0, (float(", ipl[i], ")-", minp[i], ")/(", maxp[i], "-", minp[i], ") *100.0, if(", tml[i], "<=50, 2 * ", tml[i], ", if(", tml[i], "<100.0, 2 * (100.0- ", tml[i], "), (", maxp[i], "- float(", ipl[i], "))/(", maxp[i], "-", minp[i], ") * 100.0)))'", sep=""))
+    system(paste("g.remove rast=", tml[i], sep=""))
+
+    # plotting the accumulative frequency plots for each bioclim variable
+    #d1 <- paste(envir[3], paste(x1,x3,sep=",", collapse=","), envir[4], sep=",")
+    #d2 <- paste(0, 0, paste(b, b, sep=",", collapse=","), sep=",")
+    #png(paste(ipn, ".png", sep=""))
+    #plot(strsplit(d1,",")[[1]],strsplit(d2,",")[[1]],type="l", xlab=ipn[i], ylab="% plots")
+    #dev.off()
+}
+
+system(paste("r.series output=", opc, " input=", paste(opi, collapse=","), " method=minimum", sep=""))
+
+# Optionally, calculating extra layers (min_raster, mean and median)
+# Defines categories for min_raster 
+
+if(args[7]==1){
+    system(paste("r.series output=", opc, "_MoD input=", paste(opi, collapse=","), " method=min_raster", sep=""))
+    nuv <- cbind(seq(from=0, to=length(ipn)-1, by = 1), ipn)
+    reclvar <- apply(nuv,1,function(x){paste(x[1],x[2], sep=":")})
+    tmpclas <- tempfile(pattern = "classification.rules.")
+    sink(tmpclas)
+    for(i in 1:length(reclvar)){
+        cat(reclvar[i]); cat("\n")
+    }
+    sink()
+    system(paste("r.category map=", opc, "_MoD rules=", tmpclas, sep=""))
+    unlink(tmpclas)
+}
+if(args[8]==1){
+    system(paste("r.series output=", opc, "_mean input=", paste(opi, collapse=","), " method=minimum", sep=""))
+}
+if(args[9]==1){
+    system(paste("r.series output=", opc, "_median input=", paste(opi, collapse=","), " method=median", sep=""))
+}
+
+EOF
+}
+
+# RGrass script generation
+# --------------------------
+RGRASSSCRIPT="`g.tempfile pid=$$`"
+if [ $? -ne 0 ] || [ -z "$RGRASSSCRIPT" ] ; then
+	g.message -e 'ERROR: unable to create temporary file for RGrass script' 1>&2
+    exit 1
+fi
+writeScript "$RGRASSSCRIPT"
+
+
+#=======================================================================
+## RGrass call
+#=======================================================================
+
+# Message
+g.message message='Calculating MESS layers.. this may take some time'
+
+##using R to create MESS layers
+#--slave
+R --vanilla --args "$arrIN" "${INMAPS}" "$arrOUT" "$tmpLY" "${GIS_OPT_VECTOR_INPUT}" "${GIS_OPT_COLUMNS}" "$GIS_FLAG_M" "$GIS_FLAG_K" "$GIS_FLAG_L" < "$RGRASSSCRIPT" >> "$LOGFILE" 2>&1
+if [ $? -ne 0 ] ; then
+	echo "ERROR: an error occurred during R script execution" 1>&2
+    exit 1
+fi
+
+g.message "Finished"
+
+#=======================================================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


Property changes on: grass-addons/grass7/grass7/raster/r.mess/r.mess
___________________________________________________________________
Added: svn:executable
   + 

Added: grass-addons/grass7/grass7/raster/r.mess/r.mess.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.mess/r.mess.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.mess/r.mess.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>GRASS GIS manual: r.mess</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<link rel="stylesheet" href="grassdocs.css" type="text/css">
+</head>
+<body bgcolor="white">
+
+<img src="grass_logo.png" alt="GRASS logo">
+<hr align="center" noshade="noshade" size="6">
+
+<h2>NAME</h2>
+
+<em><b>r.mess</b></em> - Computes the individual and multivariate
+environmental similarity surfaces (IESS and MESS)<br>
+
+<h2>KEYWORDS</h2>
+
+<h2>SYNOPSIS</h2>
+
+<div id="name"><b>r.mess</b><br>
+</div>
+
+<b>r.mess help</b><br>
+
+<div id="synopsis"><b>r.mess</b> [-<b>mkl</b>] <b>vector_input</b>=<em>name</em>
+<b>raster_input</b>=<em>names</em>[,<i>names</i>,...] <b>output</b>=<em>name</em>
+[<b>columns</b>=<em>string</em>] [--<b>overwrite</b>] [--<b>verbose</b>]
+[--<b>quiet</b>] </div>
+
+<div id="flags">
+<h3>Flags:</h3>
+<dl>
+  <dt><b>-m</b></dt>
+  <dd>Most dissimilar variable (MoD)</dd>
+  <dt><b>-k</b></dt>
+  <dd>Calculate MESS_mean - the mean value of the individual <br>
+  </dd>
+  <dt><b>-l</b></dt>
+  <dd>Calculate MESS_median</dd>
+  <dt><b>--overwrite</b></dt>
+  <dd>Allow output files to overwrite existing files</dd>
+  <dt><b>--verbose</b></dt>
+  <dd>Verbose module output</dd>
+  <dt><b>--quiet</b></dt>
+  <dd>Quiet module output</dd>
+</dl>
+</div>
+
+<div id="parameters">
+<h3>Parameters:</h3>
+<dl>
+  <dt><b>vector_input</b>=<em>name</em> <b>[required]</b></dt>
+  <dd>Reference points</dd>
+  <dt><b>raster_input</b>=<em>names[,<i>names</i>,...]</em> <b>[required]</b></dt>
+  <dd>Input raster map(s)</dd>
+  <dt><b>output</b>=<em>name</em> <b>[required]</b></dt>
+  <dd>Root name of the output MESS data layers</dd>
+  <dt><b>columns</b>=<em>string</em></dt>
+  <dd>Columns with environmental variables</dd>
+  <dd>Default: <em>Same names as input layers</em></dd>
+</dl>
+</div>
+
+<div id="description">
+<h2>DESCRIPTION</h2>
+<dl>
+  <p><em>r.mess</em> computes the "Multivariate Environmental
+Similarity
+Surfaces" (MESS) in GRASS using R as backend. The
+MESS index was proposed by Elith et al (2010) and is also
+implemented in the Maxent software. The MESS approach
+can be described as follows (from Elith et al 2010):
+"The multivariate environmental similarity surface (MESS) calculation
+represents how similar a point is to a reference set of points, with
+respect to a set of predictor variables (V1, V2, ...). The values in
+the MESS are
+influenced by the full distribution of the reference points, so that
+sites within the environmental range of the reference points but in
+relatively unusual environments will have a smaller value than those in
+very common environments."</p>
+  <p>This module will also compute the individual environmental
+similarity surfaces (IESS), which represents how similar a point is to
+a set of reference set of points for each of the input variable. MESS
+is then simply calculated as the minimum of its similarity with respect
+to each variable.<br>
+  <br>
+The IESS can have negative values – these are sites where the variable
+has a
+value that is outside the range in the reference set. A negative MESS
+thus represents sites where at least one variable has a value that is
+outside the range of environments over the reference set, so these are
+novel environments.<br>
+  </p>
+  <p>In addition to the MESS, which is the minimum(IESS), the r.mess
+function also allows to compute mean and medium of the IESS layers.<br>
+  </p>
+</dl>
+</div>
+
+<div id="see also">
+<h2>SEE ALSO</h2>
+There is also a similar function implemented for R using the R package <span style="font-style: italic;">raster</span>. See <a href="http://rossijeanpierre.wordpress.com/2012/08/13/computing-the-multivariate-environmental-similarity-surfaces-mess-index-in-r/">here</a>. Since October 3 2012, this function is part of the dismo package in R.
+for more information and the script.<br>
+</div>
+
+<div id="authors">
+<h2>AUTHORS</h2>
+Contact: <a href="http://ecodiv.org/contact.html">Paulo van Breugel</a>
+</div>
+
+<div id="references">
+<h2>REFERENCES</h2>
+<ol>
+  <li>Elith, J., Kearney, M., & Phillips, S. 2010. The art of
+modelling range-shifting species. Methods in Ecology and Evolution 1:
+330–342.</li>
+</ol>
+</div>
+
+<br>
+
+<br>
+
+</body></html>

Added: grass-addons/grass7/grass7/raster/r.modis/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,14 @@
+MODULE_TOPDIR =../..
+
+PGM = r.modis
+
+SUBDIRS = \
+        r.modis.download \
+        r.modis.import \
+		libmodis
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: parsubdirs htmldir
+
+install: installsubdirs

Added: grass-addons/grass7/grass7/raster/r.modis/libmodis/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/libmodis/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/libmodis/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,22 @@
+MODULE_TOPDIR = ../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+
+MODULES = downmodis rmodislib convertmodis parsemodis
+
+DSTDIR = $(ETC)/r.modis
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES))
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES))
+
+default: $(PYFILES) $(PYCFILES)
+
+$(DSTDIR):
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+install:
+	cp -r $(DSTDIR) $(INST_DIR)/etc/

Added: grass-addons/grass7/grass7/raster/r.modis/libmodis/convertmodis.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/libmodis/convertmodis.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/libmodis/convertmodis.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+#  class to convert/process modis data
+#
+#  (c) Copyright Luca Delucchi 2010
+#  Authors: Luca Delucchi
+#  Email: luca dot delucchi at iasma dot it
+#
+##################################################################
+#
+#  This MODIS Python class is licensed under the terms of GNU GPL 2.
+#  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.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU General Public License for more details.
+#
+##################################################################
+
+from datetime import *
+import string
+import os
+import sys
+import glob
+import logging
+import socket
+from ftplib import FTP
+import ftplib
+
+class convertModis:
+  """A class to convert modis data from hdf to tif using resample (from MRT tools)
+  """
+  def __init__(self, hdfname, confile, mrtpath):
+    """Initialization function :
+       hdfname = the full path to the hdf file
+       confile = the full path to the paramater file
+       mrtpath = the full path to mrt directory where inside you have bin and 
+                 data directories
+    """
+    # check if the hdf file exists
+    if os.path.exists(hdfname):
+      self.name = hdfname
+    else:
+      raise IOError('%s not exists' % hdfname)
+    # check if confile exists
+    if os.path.exists(confile):
+      self.conf = confile
+    else:
+      raise IOError('%s not exists' % confile)
+    # check if mrtpath and subdirectories exists and set environment variables
+    if os.path.exists(mrtpath):
+      if os.path.exists(os.path.join(mrtpath,'bin')):
+        self.mrtpathbin = os.path.join(mrtpath,'bin')
+        os.environ['PATH'] = "%s:%s" % (os.environ['PATH'],os.path.join(mrtpath,
+                                                                        'data'))
+      else:
+        raise IOError('The path %s not exists' % os.path.join(mrtpath,'bin'))
+      if os.path.exists(os.path.join(mrtpath,'data')):
+        self.mrtpathdata = os.path.join(mrtpath,'data')
+        os.environ['MRTDATADIR'] = os.path.join(mrtpath,'data')
+      else:
+        raise IOError('The path %s not exists' % os.path.join(mrtpath,'data'))
+    else:
+      raise IOError('The path %s not exists' % mrtpath)
+
+  def executable(self):
+    """Return the executable of resample MRT software
+    """
+    if sys.platform.count('linux') != -1:
+      if os.path.exists(os.path.join(self.mrtpathbin,'resample')):
+        return os.path.join(self.mrtpathbin,'resample')
+    elif sys.platform.count('win32') != -1:
+      if os.path.exists(os.path.join(self.mrtpathbin,'resample.exe')):
+        return os.path.join(self.mrtpath,'resample.exe')
+
+  def run(self):
+    """Exec the process"""
+    import subprocess
+    execut = self.executable()
+    if not os.path.exists(execut):
+      raise IOError('The path %s not exists, could be an erroneus path or '\
+                    + 'software') % execut
+    else:
+      subprocess.call([execut,'-p',self.conf])
+    return "The hdf file %s was converted" % self.name
+
+class createMosaic:
+  """A class to convert a mosaic of different modis tiles"""
+  def __init__(self,
+              listfile,
+              outprefix,
+              mrtpath,
+              subset = False
+              ):
+    # check if the hdf file exists
+    if os.path.exists(listfile):
+      self.basepath = os.path.split(listfile)[0]
+      self.listfiles = listfile
+      self.HDFfiles = open(listfile).readlines()
+    else:
+      raise IOError('%s not exists' % hdfname)
+    # check if mrtpath and subdirectories exists and set environment variables
+    if os.path.exists(mrtpath):
+      if os.path.exists(os.path.join(mrtpath,'bin')):
+        self.mrtpathbin = os.path.join(mrtpath,'bin')
+        os.environ['PATH'] = "%s:%s" % (os.environ['PATH'],os.path.join(mrtpath,
+                                                                        'data'))
+      else:
+        raise IOError('The path %s not exists' % os.path.join(mrtpath,'bin'))
+      if os.path.exists(os.path.join(mrtpath,'data')):
+        self.mrtpathdata = os.path.join(mrtpath,'data')
+        os.environ['MRTDATADIR'] = os.path.join(mrtpath,'data')
+      else:
+        raise IOError('The path %s not exists' % os.path.join(mrtpath,'data'))
+    else:
+      raise IOError('The path %s not exists' % mrtpath)
+    self.out = os.path.join(self.basepath, outprefix + '.hdf')
+    self.outxml = os.path.join(self.basepath, self.out + '.xml')
+    self.subset = subset
+
+  def write_mosaic_xml(self):
+    from parsemodis import parseModisMulti
+    listHDF = []
+    for i in self.HDFfiles:
+      if i.find(self.basepath) == -1:
+        print "Attection maybe you have the not full path in the HDF file list"
+        listHDF.append(os.path.join(self.basepath,i.strip()))
+      else:
+        listHDF.append(i.strip())
+    pmm = parseModisMulti(listHDF)
+    pmm.writexml(self.outxml)
+
+
+  def executable(self):
+    """Return the executable of mrtmosaic MRT software
+    """
+    if sys.platform.count('linux') != -1:
+      if os.path.exists(os.path.join(self.mrtpathbin,'mrtmosaic')):
+        return os.path.join(self.mrtpathbin,'mrtmosaic')
+    elif sys.platform.count('win32') != -1:
+      if os.path.exists(os.path.join(self.mrtpathbin,'mrtmosaic.exe')):
+        return os.path.join(self.mrtpath,'mrtmosaic.exe')
+
+  def run(self):
+    """Exect the mosaic process"""
+    import subprocess
+    execut = self.executable()
+    if not os.path.exists(execut):
+      raise IOError('The path %s not exists, could be an erroneus path or '\
+                    + 'software') % execut
+    else:
+      self.write_mosaic_xml()
+      if self.subset:
+        subprocess.call([execut,'-i',self.listfiles,'-o',self.out,'-s',self.subset], 
+                        stderr = subprocess.STDOUT)
+      else:
+        subprocess.call([execut,'-i',self.listfiles,'-o',self.out], stderr = 
+                        subprocess.STDOUT)
+    return "The mosaic file %s is created" % self.out
+
+class processModis:
+  """A class to process raw modis data from hdf to tif using swath2grid (from MRT Swath tools)
+  """
+  def __init__(self, 
+              hdfname, confile, mrtpath, 
+              inputhdf = None, outputhdf = None, geolocfile = None
+  ):
+    """Initialization function :
+       hdfname = the full path to the hdf file
+       confile = the full path to the paramater file
+       mrtpath = the full path to mrt directory where inside you have bin and 
+                 data directories
+    """
+    # check if the hdf file exists
+    if os.path.exists(hdfname):
+      self.name = hdfname
+    else:
+      raise IOError('%s not exists' % hdfname)
+    # check if confile exists
+    if os.path.exists(confile):
+      self.conf = confile
+    else:
+      raise IOError('%s not exists' % confile)
+    # check if mrtpath and subdirectories exists and set environment variables
+    if os.path.exists(mrtpath):
+      if os.path.exists(os.path.join(mrtpath,'bin')):
+        self.mrtpathbin = os.path.join(mrtpath,'bin')
+        os.environ['PATH'] = "%s:%s" % (os.environ['PATH'],os.path.join(mrtpath,
+                                                                        'data'))
+      else:
+        raise IOError('The path %s not exists' % os.path.join(mrtpath,'bin'))
+      if os.path.exists(os.path.join(mrtpath,'data')):
+        self.mrtpathdata = os.path.join(mrtpath,'data')
+        os.environ['MRTDATADIR'] = os.path.join(mrtpath,'data')
+      else:
+        raise IOError('The path %s not exists' % os.path.join(mrtpath,'data'))
+    else:
+      raise IOError('The path %s not exists' % mrtpath)
+
+  def executable(self):
+    """Return the executable of resample MRT software
+    """
+    if sys.platform.count('linux') != -1:
+      if os.path.exists(os.path.join(self.mrtpathbin,'swath2grid')):
+        return os.path.join(self.mrtpathbin,'swath2grid')
+    elif sys.platform.count('win32') != -1:
+      if os.path.exists(os.path.join(self.mrtpathbin,'swath2grid.exe')):
+        return os.path.join(self.mrtpath,'swath2grid.exe')
+
+  def run(self):
+    """Exec the process"""
+    import subprocess
+    execut = self.executable()
+    if not os.path.exists(execut):
+      raise IOError('The path %s not exists, could be an erroneus path or '\
+                    + 'software') % execut
+    else:
+      subprocess.call([execut,'-pf=%s' % self.conf])
+    return "The hdf file %s was converted" % self.name

Added: grass-addons/grass7/grass7/raster/r.modis/libmodis/downmodis.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/libmodis/downmodis.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/libmodis/downmodis.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,381 @@
+#!/usr/bin/env python
+#  class to download modis data
+#
+#  (c) Copyright Luca Delucchi 2010
+#  Authors: Luca Delucchi
+#  Email: luca dot delucchi at iasma dot it
+#
+##################################################################
+#
+#  This MODIS Python class is licensed under the terms of GNU GPL 2.
+#  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.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU General Public License for more details.
+#
+##################################################################
+
+from datetime import *
+import string
+import os
+import sys
+import glob
+import logging
+import socket
+from ftplib import FTP
+import ftplib
+
+class downModis:
+  """A class to download MODIS data from NASA FTP repository"""
+  def __init__(self, 
+                password,
+                destinationFolder,
+                user = "anonymous",
+                url = "e4ftl01.cr.usgs.gov",
+                tiles = None,
+                path = "MOLT/MOD11A1.005",
+                today = None,
+                enddate = None,
+                delta = 10,
+                jpg = False,
+                debug = False
+              ):
+    """Initialization function :
+        password = is your password, usually your email address
+        destinationFolder = where the files will be stored
+        user = your username, by default anonymous
+        url = the url where to download the MODIS data
+        path = the directory where the data that you want to download are 
+               stored on the ftp server
+        tiles = a list of tiles that you want to download, None == all tiles
+        today = the day to start downloading; in order to pass a date different from
+                today use the format YYYY-MM-DD
+        delta = timelag i.e. the number of days starting from today 
+                (backwards
+
+        Creates a ftp instance, connects user to ftp server and goes into the 
+        directory where the MODIS data are stored
+    """
+
+    # url modis
+    self.url = url
+    # user for download
+    self.user = user
+    # password for download
+    self.password = password
+    # directory where data are collected
+    self.path = path
+    # tiles to downloads
+    if tiles:
+        self.tiles = tiles.split(',')
+    else:
+        self.tiles = tiles
+    # set destination folder
+    if os.access(destinationFolder,os.W_OK):
+      self.writeFilePath = destinationFolder
+    else:
+      raise IOError("Folder to store downloaded files does not exist or is not" \
+    + "writeable")
+    # return the name of product
+    if len(self.path.split('/')) == 2:
+      self.product = self.path.split('/')[1]
+    elif len(self.path.split('/')) == 3:
+      self.product = self.path.split('/')[2]
+    # write a file with the name of file downloaded
+    self.filelist = open(os.path.join(self.writeFilePath, 'listfile' \
+    + self.product + '.txt'),'w')
+    # set jpg download
+    self.jpeg = jpg
+    # today
+    self.today = today
+    # force the last day
+    self.enday = enddate
+    # delta of days
+    self.delta = delta
+    # status of tile download
+    self.status = True
+    # for debug, you can download only xml files
+    self.debug = debug
+    # for logging
+    LOG_FILENAME = os.path.join(self.writeFilePath, 'modis' \
+    + self.product + '.log')
+    LOGGING_FORMAT='%(asctime)s - %(levelname)s - %(message)s'
+    logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, \
+    format=LOGGING_FORMAT)
+    self.nconnection = 0
+    
+  def connectFTP(self, ncon = 20):
+    """ Set connection to ftp server, move to path where data are stored
+    and create a list of directory for all days"""
+    self.nconnection += 1
+    try:
+      # connect to ftp server
+      self.ftp = FTP(self.url)
+      self.ftp.login(self.user,self.password)
+      # enter in directory
+      self.ftp.cwd(self.path)
+      self.dirData = []
+      # return data inside directory
+      self.ftp.dir(self.dirData.append)
+      # reverse order of data for have first the nearest to today
+      self.dirData.reverse()
+      # check if dirData contain only directory, delete all files
+      self.dirData = [elem.split()[-1] for elem in self.dirData if elem.startswith("d")]
+      if self.debug==True:
+        logging.debug("Open connection %s" % self.url)
+    except (EOFError, ftplib.error_perm), e:
+      logging.error('Error in connection: %s' % e)
+      if self.nconnection <= ncon:
+        self.connectFTP()
+
+  def closeFTP(self):
+    """ Close ftp connection """
+    self.ftp.quit()
+    self.filelist.close()
+    if self.debug==True:
+      logging.debug("Close connection %s" % self.url)
+
+  def setDirectoryIn(self,day):
+    """ Enter in the directory of the day """
+    try:
+      self.ftp.cwd(day)
+    except (ftplib.error_reply,socket.error), e:
+      logging.error("Error %s entering in directory %s" % e, day)
+      self.setDirectoryIn(day)
+
+  def setDirectoryOver(self):
+    """ Come back to old path """
+    try:
+      self.ftp.cwd('..')
+    except (ftplib.error_reply,socket.error), e:
+      logging.error("Error %s when try to come back" % e)
+      self.setDirectoryOver()
+
+  def str2date(self,strin):
+      """Return a date object from a string"""
+      todaySplit = strin.split('-')
+      return date(int(todaySplit[0]), int(todaySplit[1]),int(todaySplit[2]))
+
+  def getToday(self):
+    """Return the first day for start to download"""
+    if self.today == None:
+      # set today variable to today
+      self.today = date.today()
+    else:
+      # set today variable to data pass from user
+      self.today = self.str2date(self.today)
+      # set enday variable to data
+    if self.enday != None:
+      self.enday = self.str2date(self.enday)
+      
+  def getListDays(self):
+      """ Return a list of all selected days """
+      self.getToday()
+
+      today_s = self.today.strftime("%Y.%m.%d")
+      # dirData is reverse sorted
+      for i, d in enumerate(self.dirData):
+        if d <= today_s:
+          today_avail = d
+          today_index = i
+          break
+      else:
+        logging.error("No data available for requested days")
+        import sys
+        sys.exit()
+      days = self.dirData[today_index:][:self.delta]
+      # this is useful for 8/16 days data, delta could download more images
+      # that you want
+      if self.enday != None:
+        enday_s = self.enday.strftime("%Y.%m.%d")
+        delta = 0
+        # it make a for cicle from the last value and find the internal delta
+        #to remove file outside temporaly range
+        for i in range(-(len(days)),0):
+          if days[i] < enday_s:
+            break
+          else:
+            delta = delta + 1
+        # remove days outside new delta
+        days = days[:delta]
+      return days
+
+  def getFilesList(self):
+    """ Create a list of files to download, it is possible choose to download 
+    also the jpeg files or only the hdf files"""
+    def cicle_file(jpeg=False,tile=True):
+      finalList = []
+      for i in self.listfiles:
+        File = i.split('.')
+        # distinguish jpeg files from hdf files by the number of index 
+        # where find the tile index
+        if not tile and not (File.count('jpg') or File.count('BROWSE')):
+          finalList.append(i)
+        if tile and self.tiles.count(File[3]) == 1 and jpeg: #is a jpeg of tiles number
+          finalList.append(i)
+        if tile and self.tiles.count(File[2]) == 1: #is a hdf of tiles number
+          finalList.append(i)
+      return finalList
+
+    # return the file's list inside the directory of each day
+    try:
+      self.listfiles = self.ftp.nlst() 
+      # download also jpeg
+      if self.jpeg:
+        # finallist is ugual to all file with jpeg file
+        if not self.tiles:
+          finalList = self.listfiles
+        # finallist is ugual to tiles file with jpeg file
+        else:
+          finalList = cicle_file(jpeg=True)
+      # not download jpeg
+      else:
+        if not self.tiles:
+          finalList = cicle_file(tile=False)          
+        else:
+          finalList = cicle_file()
+      if self.debug==True:
+        logging.debug("The number of file to download is: %i" % len(finalList))
+      return finalList
+    except (ftplib.error_reply,socket.error), e:
+      logging.error("Error %s when try to receive list of files" % e)
+      self.getFilesList()
+
+  def checkDataExist(self,listNewFile, move = 0):
+    """ Check if a data already exists in the directory of download 
+    Move serve to know if function is called from download or move function"""
+    fileInPath = []
+    # add all files in the directory where we will save new modis data
+    for f in os.listdir(self.writeFilePath):
+      if os.path.isfile(os.path.join(self.writeFilePath, f)):
+        fileInPath.append(f)
+    # different return if this method is used from downloadsAllDay() or 
+    # moveFile()
+    if move == 0:
+      listOfDifferent = list(set(listNewFile) - set(fileInPath))
+    elif move == 1:
+      listOfDifferent = list(set(fileInPath) - set(listNewFile))
+    return listOfDifferent
+
+  def getNewerVersion(self,oldFile,newFile):
+    """ Return newer version of a file"""
+    oldFileSplit = oldFile.split('.')
+    newFileSplit = newFile.split('.')
+    if oldFileSplit[4] > newFileSplit[4]:
+      return oldFile
+    else:
+      return newFile
+
+  def downloadFile(self,filDown,filSave):
+    """Download the single file"""
+    #try to download file
+    try:
+      self.ftp.retrbinary("RETR " + filDown, filSave.write)
+      self.filelist.write("%s\n" % filDown)
+      if self.debug==True:
+        logging.debug("File %s downloaded" % filDown)
+    #if it have an error it try to download again the file
+    except (ftplib.error_reply,socket.error), e:
+      logging.error("Cannot download %s, retry.." % filDown)
+      self.connectFTP()
+      self.downloadFile(filDown,filSave)
+
+  def dayDownload(self,listFilesDown):
+    """ Downloads tiles are in files_hdf_consider """
+    # for each file in files' list
+    for i in listFilesDown:
+        fileSplit = i.split('.')
+        filePrefix = fileSplit[0] + '.' + fileSplit[1] + '.' + fileSplit[2] \
+        + '.' + fileSplit[3]
+        #for debug, download only xml
+        if (self.debug and fileSplit[-1] == 'xml') or not self.debug:
+          # check data exists in the return directory, if it doesn't exists
+          oldFile = glob.glob1(self.writeFilePath, filePrefix + "*" \
+          + fileSplit[-1])
+          numFiles = len(oldFile)
+          if numFiles == 0:
+            file_hdf = open(os.path.join(self.writeFilePath,i), "wb")
+          elif numFiles == 1:
+            # check the version of file  
+            fileDown = self.getNewerVersion(oldFile[0],i)
+            if fileDown != oldFile[0]:
+              os.remove(os.path.join(self.writeFilePath,oldFile[0]))
+              file_hdf = open(os.path.join(self.writeFilePath,fileDown), "wb")
+          elif numFiles > 1:
+            logging.error("There are to much files for %s" % i)
+            #raise EOFError("There are to much file with the same prefix")
+          if numFiles == 0 or (numFiles == 1 and fileDown != oldFile[0]):
+            self.downloadFile(i,file_hdf)
+
+  def downloadsAllDay(self):
+    """ Downloads all the tiles considered """
+    #return the days to download
+    days = self.getListDays()
+    if self.debug==True:
+      logging.debug("The number of days to download is: %i" % len(days))
+    #for each day
+    for day in days:
+      #enter in the directory of day
+      self.setDirectoryIn(day)
+      #obtain list of all files
+      listAllFiles = self.getFilesList()
+      #obtain list of files to download
+      listFilesDown = self.checkDataExist(listAllFiles)
+      #download files for a day
+      self.dayDownload(listFilesDown)
+      self.setDirectoryOver()
+    self.closeFTP()
+    if self.debug==True:
+      logging.debug("Download terminated")
+    return 0
+
+  def debugLog(self):
+    # create logger
+    logger = logging.getLogger("PythonLibModis debug")
+    logger.setLevel(logging.DEBUG)
+    # create console handler and set level to debug
+    ch = logging.StreamHandler()
+    ch.setLevel(logging.DEBUG)
+    # create formatter
+    formatter = logging.Formatter("%(asctime)s - %(name)s - " \
+                + "%(levelname)s - %(message)s")
+    # add formatter to ch
+    ch.setFormatter(formatter)
+    # add ch to logger
+    logger.addHandler(ch)
+    return logger
+
+  def debugDays(self):
+    """This function is useful to debug the number of days"""
+    logger = debugLog()
+    days = self.getListDays()
+    # if lenght of list of days and the delta of day they are different
+    if len(days) != self.delta:
+      # for each day
+      for i in range(1,self.delta+1):
+        # calculate the current day
+        delta = timedelta(days = i)
+        day = self.today - delta
+        day = day.strftime("%Y.%m.%d") 
+        # check if day is in the days list
+        if day not in days:
+          logger.critical("This day %s is not present on list" % day)
+    # the lenght of list of days and delta are ugual
+    else:
+      logger.info("All right!!")
+    
+  def debugMaps(self):
+    """This function is useful to debug the number of maps to download for 
+    each day"""
+    logger = debugLog()
+    days = self.getListDays()
+    for day in days:
+      self.setDirectoryIn(day)
+      listAllFiles = self.getFilesList()
+      string = day + ": " + str(len(listAllFiles)) + "\n"
+      logger.debug(string)
+      self.setDirectoryOver()   

Added: grass-addons/grass7/grass7/raster/r.modis/libmodis/parsemodis.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/libmodis/parsemodis.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/libmodis/parsemodis.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,699 @@
+#!/usr/bin/env python
+#  class to parse modis data
+#
+#  (c) Copyright Luca Delucchi 2010
+#  Authors: Luca Delucchi
+#  Email: luca dot delucchi at iasma dot it
+#
+##################################################################
+#
+#  This MODIS Python class is licensed under the terms of GNU GPL 2.
+#  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.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU General Public License for more details.
+#
+##################################################################
+
+from datetime import *
+import string
+import os
+import sys
+import glob
+import logging
+import socket
+from ftplib import FTP
+import ftplib
+
+## lists of parameters accepted by resample MRT software
+# projections
+PROJ_LIST = ['AEA','GEO', 'HAM', 'IGH', 'ISIN', 'LA', 'LCC', 'MOL', 'PS', 
+                    'SIN','TM', 'UTM', 'MERCAT']
+# resampling
+RESAM_LIST = ['NEAREST_NEIGHBOR', 'BICUBIC', 'CUBIC_CONVOLUTION', 'NONE']
+RESAM_LIST_SWATH = ['NN', 'BI', 'CC']
+
+# datum
+DATUM_LIST = ['NODATUM', 'NAD27', 'NAD83', 'WGS66', 'WGS72', 'WGS84']
+SPHERE_LIST = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
+
+class parseModis:
+  """Class to parse MODIS xml files, it also can create the parameter 
+    configuration file for resampling with the MRT software
+  """
+  def __init__(self, filename):
+    """Initialization function :
+       filename = the name of MODIS hdf file
+    """
+    from xml.etree import ElementTree
+    if os.path.exists(filename):
+      # hdf name
+      self.hdfname = filename
+    else:
+      raise IOError('%s not exists' % self.hdfname)
+
+    if os.path.exists(self.hdfname + '.xml'):
+      # xml hdf name
+      self.xmlname = self.hdfname + '.xml'
+    else:
+      raise IOError('%s not exists' % self.hdfname + '.xml')
+
+    # tif name for the output file for resample MRT software
+    self.tifname = self.hdfname.replace('.hdf','.tif')
+    with open(self.xmlname) as f:
+      self.tree = ElementTree.parse(f)
+    # return the code of tile for conf file
+    self.code = os.path.split(self.hdfname)[1].split('.')[-2]
+    self.path = os.path.split(self.hdfname)[0]
+
+  def __str__(self):
+    """Print the file without xml tags"""
+    retString = ""
+    try:
+      for node in self.tree.iter():
+        if node.text.strip() != '':
+          retString = "%s = %s\n" % (node.tag,node.text) 
+    except:
+      for node in self.tree.getiterator():
+        if node.text.strip() != '':
+          retString = "%s = %s\n" % (node.tag,node.text) 
+    return retString
+
+  def getRoot(self):
+    """Set the root element"""
+    self.rootree = self.tree.getroot()
+
+  def retDTD(self):
+    """Return the DTDVersion element"""
+    self.getRoot()
+    return self.rootree.find('DTDVersion').text
+
+  def retDataCenter(self):
+    """Return the DataCenterId element"""
+    self.getRoot()
+    return self.rootree.find('DataCenterId').text
+
+  def getGranule(self):
+    """Set the GranuleURMetaData element"""
+    self.getRoot()
+    self.granule = self.rootree.find('GranuleURMetaData')
+
+  def retGranuleUR(self):
+    """Return the GranuleUR element"""
+    self.getGranule()
+    return self.granule.find('GranuleUR').text
+
+  def retDbID(self):
+    """Return the DbID element"""
+    self.getGranule()
+    return self.granule.find('DbID').text
+
+  def retInsertTime(self):
+    """Return the DbID element"""
+    self.getGranule()
+    return self.granule.find('InsertTime').text
+
+  def retLastUpdate(self):
+    """Return the DbID element"""
+    self.getGranule()
+    return self.granule.find('LastUpdate').text
+
+  def retCollectionMetaData(self):
+    """Return the CollectionMetaData element"""
+    self.getGranule()
+    collect = {}
+    for i in self.granule.find('CollectionMetaData').getiterator():
+      if i.text.strip() != '':
+        collect[i.tag] = i.text
+    return collect
+
+  def retDataFiles(self):
+    """Return the DataFiles element"""
+    self.getGranule()
+    collect = {}
+    datafiles = self.granule.find('DataFiles')
+    for i in datafiles.find('DataFileContainer').getiterator():
+      if i.text.strip() != '':
+        collect[i.tag] = i.text
+    return collect
+
+  def retDataGranule(self):
+    """Return the ECSDataGranule elements"""
+    self.getGranule()
+    datagran = {}
+    for i in self.granule.find('ECSDataGranule').getiterator():
+      if i.text.strip() != '':
+        datagran[i.tag] = i.text
+    return datagran
+
+  def retPGEVersion(self):
+    """Return the PGEVersion element"""
+    self.getGranule()
+    return self.granule.find('PGEVersionClass').find('PGEVersion').text
+
+  def retRangeTime(self):
+    """Return the RangeDateTime elements inside a dictionary with the element
+       name like dictionary key
+    """
+    self.getGranule()
+    rangeTime = {}
+    for i in self.granule.find('RangeDateTime').getiterator():
+      if i.text.strip() != '':
+        rangeTime[i.tag] = i.text
+    return rangeTime
+
+  def retBoundary(self):
+    """Return the maximum extend of the MODIS file inside a dictionary"""
+    self.getGranule()
+    self.boundary = []
+    lat = []
+    lon = []
+    spatialContainer = self.granule.find('SpatialDomainContainer')
+    horizontal = spatialContainer.find('HorizontalSpatialDomainContainer')
+    boundary = horizontal.find('GPolygon').find('Boundary')
+    for i in boundary.findall('Point'):
+      la = float(i.find('PointLongitude').text)
+      lo = float(i.find('PointLatitude').text)
+      lon.append(la)
+      lat.append(lo)
+      self.boundary.append({'lat': la, 'lon':lo})
+    extent = {'min_lat':min(lat),'max_lat':max(lat),'min_lon':min(lon),
+                'max_lon':max(lon)}
+    return extent
+
+  def retMeasure(self):
+    """Return statistics inside a dictionary"""
+    value = {}
+    self.getGranule()
+    mes = self.granule.find('MeasuredParameter')
+    mespc = mes.find('MeasuredParameterContainer')
+    value['ParameterName'] = mespc.find('ParameterName').text
+    meStat = mespc.find('QAStats')
+    qastat = {}
+    for i in meStat.getiterator():
+      if i.tag != 'QAStats':
+        qastat[i.tag] = i.text
+    value['QAStats'] = qastat
+    meFlag = mespc.find('QAFlags')
+    flagstat = {}
+    for i in meFlag.getiterator():
+      if i.tag != 'QAFlags':
+        flagstat[i.tag] = i.text
+    value['QAFlags'] = flagstat
+    return value
+
+  def retPlatform(self):
+    """Return the platform values inside a dictionary."""
+    value = {}
+    self.getGranule()
+    plat = self.granule.find('Platform')
+    value['PlatformShortName'] = plat.find('PlatformShortName').text
+    instr = plat.find('Instrument')
+    value['InstrumentShortName'] = instr.find('InstrumentShortName').text
+    sensor = instr.find('Sensor')
+    value['SensorShortName'] = sensor.find('SensorShortName').text
+    return value
+
+  def retPSA(self):
+    """Return the PSA values inside a dictionary, the PSAName is he key and
+       and PSAValue is the value
+    """
+    value = {}
+    self.getGranule()
+    psas = self.granule.find('PSAs')
+    for i in psas.findall('PSA'):
+      value[i.find('PSAName').text] = i.find('PSAValue').text
+    return value
+
+  def retInputGranule(self):
+    """Return the input files used to process the considered file"""
+    value = []
+    self.getGranule()
+    for i in self.granule.find('InputGranule').getiterator():
+      if i.tag != 'InputGranule':
+        value.append(i.text)
+    return value
+
+  def retBrowseProduct(self):
+    """Return the PGEVersion element"""
+    self.getGranule()
+    try:
+        value = self.granule.find('BrowseProduct').find('BrowseGranuleId').text
+    except:
+        value = None
+    return value    
+
+  def confResample(self, spectral, res = None, output = None, datum = 'WGS84',
+                  resampl = 'NEAREST_NEIGHBOR', projtype = 'GEO',  utm = None,
+                  projpar = '( 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 )',
+                  ):
+    """Create the parameter file to use with resample MRT software to create
+       tif file
+        spectral = the spectral subset to use, look the product table to 
+                   understand the layer that you want use. 
+                   For example: 
+                    - NDVI ( 1 1 1 0 0 0 0 0 0 0 0 0) copy only layer NDVI, EVI 
+                      and QA VI the other layers are not used
+                    - LST ( 1 1 0 0 1 1 0 0 0 0 0 0 ) copy only layer daily and
+                      nightly temperature and QA
+        res = the resolution for the output file, it must be set in the map 
+              unit of output projection system. The software will use the original
+              resolution of input file if res it isn't set
+        output = the output name, if it doesn't set will use the prefix name of 
+                 input hdf file
+        utm = the UTM zone if projection system is UTM
+        resampl = the type of resampling, the valid values are: NN (nearest 
+                  neighbor), BI (bilinear), CC (cubic convolution)
+        projtype = the output projection system, the valid values are: AEA 
+                   (Albers Equal Area), ER (Equirectangular), GEO (Geographic 
+                   Latitude/Longitude), HAM (Hammer), ISIN (Integerized Sinusoidal), 
+                   IGH (Interrupted Goode Homolosine), LA (Lambert Azimuthal), 
+                   LCC (LambertConformal Conic), MERCAT (Mercator), MOL (Mollweide), 
+                   PS (Polar Stereographic), SIN ()Sinusoidal), UTM (Universal 
+                   TransverseMercator)
+        datum = the datum to use, the valid values are: NAD27, NAD83, WGS66,
+                WGS76, WGS84, NODATUM
+        projpar = a list of projection parameters, for more info check the 
+                  "Appendix C" of MODIS reprojection tool user’s manual
+                  https://lpdaac.usgs.gov/content/download/4831/22895/file/mrt41_usermanual_032811.pdf
+
+        """
+    #check if spectral it's write with correct construct ( value )
+    if string.find(spectral, '(') == -1 or  string.find(spectral, ')') == -1:
+      raise IOError('ERROR: The spectral string should be similar to: ( 1 0 )')
+    # output name
+    if not output:
+      fileout = self.tifname
+    else:
+      fileout = output
+    # the name of the output parameters files for resample MRT software
+    filename = os.path.join(self.path,'%s_mrt_resample.conf' % self.code)
+    # if the file already exists it remove it 
+    if os.path.exists(filename):
+      os.remove(filename)
+    # open the file
+    conFile = open(filename, 'w')
+    conFile.write("INPUT_FILENAME = %s\n" % self.hdfname)
+    conFile.write("SPECTRAL_SUBSET = %s\n" % spectral)
+    conFile.write("SPATIAL_SUBSET_TYPE = INPUT_LAT_LONG\n")
+    # return the boundary from the input xml file
+    bound = self.retBoundary()
+    # Order:  UL: N W  - LR: S E
+    conFile.write("SPATIAL_SUBSET_UL_CORNER = ( %f %f )\n" % (bound['max_lat'],
+                                                              bound['min_lon']))
+    conFile.write("SPATIAL_SUBSET_LR_CORNER = ( %f %f )\n" % (bound['min_lat'],
+                                                              bound['max_lon']))
+    conFile.write("OUTPUT_FILENAME = %s\n" % fileout)
+    # if resampl is in resam_list set the parameter otherwise return an error
+    if resampl in RESAM_LIST:
+      conFile.write("RESAMPLING_TYPE = %s\n" % resampl)
+    else:
+      raise IOError('The resampling type %s is not supportet.\n' \
+                   'The resampling type supported are %s' % (resampl,RESAM_LIST))
+    # if projtype is in proj_list set the parameter otherwise return an error
+    if projtype in PROJ_LIST:
+      conFile.write("OUTPUT_PROJECTION_TYPE = %s\n" % projtype)
+    else:
+      raise IOError('The projection type %s is not supported.\n' \
+                   'The projections supported are %s' % (projtype,PROJ_LIST))
+    conFile.write("OUTPUT_PROJECTION_PARAMETERS = %s\n" % projpar)
+    # if datum is in datum_list set the parameter otherwise return an error
+    if datum in DATUM_LIST:
+      conFile.write("DATUM = %s\n" % datum)
+    else:
+      raise IOError('The datum %s is not supported.\n' \
+                   'The datum supported are %s' % (datum,DATUM_LIST))
+    # if utm is not None write the UTM_ZONE parameter in the file
+    if utm:
+      conFile.write("UTM_ZONE = %s\n" % utm)
+    # if res is not None write the OUTPUT_PIXEL_SIZE parameter in the file
+    if res:
+      conFile.write("OUTPUT_PIXEL_SIZE = %i\n" % res)
+    conFile.close()
+    return filename
+
+  def confResample_swath(self, sds, geoloc, res, output = None, 
+                  sphere = '8', resampl = 'NN', projtype = 'GEO',  utm = None,
+                  projpar = '0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0',
+                  ):
+    """Create the parameter file to use with resample MRT software to create
+       tif file
+        sds = Name of band/s (Science Data Set) to resample
+        geoloc = Name geolocation file (example MOD3, MYD3)
+        res = the resolution for the output file, it must be set in the map 
+              unit of output projection system. The software will use the original
+              resolution of input file if res it isn't set
+        output = the output name, if it doesn't set will use the prefix name of 
+                 input hdf file
+        sphere = Output sphere number. Valid options are: 
+                 0=Clarke 1866, 1=Clarke 1880, 2=Bessel, 3=International 1967, 
+                 4=International 1909, 5=WGS 72, 6=Everest, 7=WGS 66, 
+                 8=GRS1980/WGS 84, 9=Airy, 10=Modified Everest, 11=Modified Airy, 
+                 12=Walbeck, 13=Southeast Asia, 14=Australian National, 
+                 15=Krassovsky, 16=Hough, 17=Mercury1960, 18=Modified Mercury1968, 
+                 19=Sphere 19 (Radius 6370997), 20=MODIS Sphere (Radius 6371007.181)
+        resampl = the type of resampling, the valid values are: NN (nearest 
+                  neighbor), BI (bilinear), CC (cubic convolution)
+        projtype = the output projection system, the valid values are: 
+                   AEA (Albers Equal Area), ER (Equirectangular), 
+                   GEO (Geographic Latitude/Longitude), HAM (Hammer), 
+                   ISIN (Integerized Sinusoidal),IGH (Interrupted Goode Homolosine), 
+                   LA (Lambert Azimuthal), LCC (LambertConformal Conic),
+                   MERCAT (Mercator), MOL (Mollweide), PS (Polar Stereographic),
+                   SIN ()Sinusoidal), UTM (Universal TransverseMercator)
+        utm = the UTM zone if projection system is UTM
+        projpar = a list of projection parameters, for more info check the 
+                  "Appendix C" of MODIS reprojection tool user’s manual
+                  https://lpdaac.usgs.gov/content/download/4831/22895/file/mrt41_usermanual_032811.pdf
+        """
+    # output name
+    if not output:
+      fileout = self.tifname
+    else:
+      fileout = output
+    # the name of the output parameters files for resample MRT software
+    filename = os.path.join(self.path,'%s_mrt_resample.prm' % self.code)
+    # if the file already exists it remove it 
+    if os.path.exists(filename):
+      os.remove(filename)
+    # open the file
+    conFile = open(filename, 'w')
+    conFile.write("INPUT_FILENAME = %s\n" % self.hdfname)
+    conFile.write("GEOLOCATION_FILENAME = %s\n" % geoloc)
+    conFile.write("INPUT_SDS_NAME = %s\n" % sds)
+    conFile.write("OUTPUT_SPATIAL_SUBSET_TYPE = LAT_LONG\n")
+    # return the boundary from the input xml file
+    bound = self.retBoundary()
+    # Order:  UL: N W  - LR: S E
+    conFile.write("OUTPUT_SPACE_UPPER_LEFT_CORNER (LONG LAT) = %f %f\n" % (bound['max_lat'],
+                                                              bound['min_lon']))
+    conFile.write("OUTPUT_SPACE_LOWER_RIGHT_CORNER (LONG LAT) = %f %f\n" % (bound['min_lat'],
+                                                              bound['max_lon']))
+    conFile.write("OUTPUT_FILENAME = %s\n" % fileout)
+    conFile.write("OUTPUT_FILE_FORMAT = GEOTIFF_FMT\n")
+    # if resampl is in resam_list set the parameter otherwise return an error
+    if resampl in RESAM_LIST_SWATH:
+      conFile.write("KERNEL_TYPE (CC/BI/NN) = %s\n" % resampl)
+    else:
+      raise IOError('The resampling type %s is not supportet.\n' \
+                   'The resampling type supported are %s' % (resampl,RESAM_LIST_SWATH))
+    # if projtype is in proj_list set the parameter otherwise return an error
+    if projtype in PROJ_LIST:
+      conFile.write("OUTPUT_PROJECTION_NUMBER = %s\n" % projtype)
+    else:
+      raise IOError('The projection type %s is not supported.\n' \
+                   'The projections supported are %s' % (projtype,PROJ_LIST))
+    conFile.write("OUTPUT_PROJECTION_PARAMETER = %s\n" % projpar)
+    # if sphere is in sphere_list set the parameter otherwise return an error
+    if int(sphere) in SPHERE_LIST:
+      conFile.write("OUTPUT_PROJECTION_SPHERE = %s\n" % sphere)
+    else:
+      raise IOError('The sphere %s is not supported.\n' \
+                   'The spheres supported are %s' % (sphere,SPHERE_LIST))
+    # if utm is not None write the UTM_ZONE parameter in the file
+    if utm:
+      if utm < '-60' or utm > '60':
+        raise IOError('The valid UTM zone are -60 to 60')
+      else:
+        conFile.write("OUTPUT_PROJECTION_ZONE = %s\n" % utm)
+    # if res is not None write the OUTPUT_PIXEL_SIZE parameter in the file
+    if res:
+      conFile.write("OUTPUT_PIXEL_SIZE = %f\n" % res)
+    conFile.close()
+    return filename
+
+class parseModisMulti:
+  """A class to some variable for the xml file of a mosaic
+  """
+  def __init__(self,hdflist):
+    """hdflist = python list containing the hdf files"""
+    from xml.etree import ElementTree
+    self.ElementTree = ElementTree
+    self.hdflist = hdflist
+    self.parModis = []
+    self.nfiles = 0
+    # for each hdf files create a parseModis object
+    for i in hdflist:
+      self.parModis.append(parseModis(i))
+      self.nfiles += 1
+
+  def _checkval(self,vals):
+    """Internal function to return values from list"""
+    if vals.count(vals[0]) == self.nfiles:
+      return [vals[0]]
+    else:
+      outvals = []
+      for i in vals:
+        if outvals.count(i) == 0:
+          outvals.append(i)
+      return outvals
+      
+  def _checkvaldict(self,vals):
+    """Internal function to return values from dictionary"""
+    keys = vals[0].keys()
+    outvals = {}
+    for k in keys:
+      valtemp = []
+      for v in vals:
+        valtemp.append(v[k])
+      if valtemp.count(valtemp[0]) == self.nfiles:
+        outvals[k] = valtemp[0]
+      else:
+        raise IOError('Something wrong reading XML files')
+      
+    return outvals
+
+  def _minval(self, vals):
+    """Internal function to return the minimum value"""
+    outval = vals[0]
+    for i in range(1,len(vals)):
+      if outval > i:
+        outval = i
+    return outval
+    
+  def _maxval(self, vals):
+    """Internal function to return the maximum value"""
+    outval = vals[0]
+    for i in range(1,len(vals)):
+      if outval < i:
+        outval = i
+    return outval
+    
+  def _cicle_values(self, ele,values):
+    """Internal function to add values from a dictionary"""
+    for k,v in values.iteritems():
+      elem = self.ElementTree.SubElement(ele,k)
+      elem.text = v
+
+  def _addPoint(self,obj,lon,lat):
+    """Internal function to add a point in boundary xml tag"""
+    pt = self.ElementTree.SubElement(obj, 'Point')
+    ptlon = self.ElementTree.SubElement(pt, 'PointLongitude')
+    ptlon.text = str(self.boundary[lon])
+    ptlat = self.ElementTree.SubElement(pt, 'PointLatitude')
+    ptlat.text = str(self.boundary[lat])
+
+  def valDTD(self,obj):
+    """Function to add DTDVersion"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retDTD())
+    for i in self._checkval(values):
+      dtd = self.ElementTree.SubElement(obj,'DTDVersion')
+      dtd.text = i
+
+  def valDataCenter(self,obj):
+    """Function to add DataCenter"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retDataCenter())
+    for i in self._checkval(values):
+      dci = self.ElementTree.SubElement(obj,'DataCenterId')
+      dci.text = i
+      
+  def valGranuleUR(self,obj):
+    """Function to add GranuleUR"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retGranuleUR())
+    for i in self._checkval(values):
+      gur = self.ElementTree.SubElement(obj,'GranuleUR')
+      gur.text = i
+
+  def valDbID(self,obj):
+    """Function to add DbID"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retDbID())
+    for i in self._checkval(values):
+      dbid = self.ElementTree.SubElement(obj,'DbID')
+      dbid.text = i
+      
+  def valInsTime(self,obj):
+    """TODO"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retInsertTime())
+    obj.text = self._minval(values)
+  
+  def valCollectionMetaData(self,obj):
+    """Function to add CollectionMetaData"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retCollectionMetaData())
+    self._cicle_values(obj,self._checkvaldict(values))
+  
+  def valDataFiles(self, obj):
+    """Function to add DataFileContainer"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retDataFiles())
+    for i in values:
+      dfc = self.ElementTree.SubElement(obj, 'DataFileContainer')
+      self._cicle_values(dfc,i)
+    
+  def valPGEVersion(self,obj):
+    """Function to add PGEVersion"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retPGEVersion())
+    for i in self._checkval(values):
+      pge = self.ElementTree.SubElement(obj,'PGEVersion')
+      pge.text = i
+  
+  def valRangeTime(self,obj):
+    """Function to add RangeDateTime"""
+    values = []
+    for i in self.parModis:
+      values.append(i.retRangeTime())
+    self._cicle_values(obj,self._checkvaldict(values))
+  
+  def valBound(self):
+    """Function return the bounding box of mosaic"""
+    boundary = self.parModis[0].retBoundary()
+    for i in range(1,len(self.parModis)):
+      bound = self.parModis[i].retBoundary()
+      if bound['min_lat'] < boundary['min_lat']:
+        boundary['min_lat'] = bound['min_lat']
+      if bound['min_lon'] < boundary['min_lon']:
+        boundary['min_lon'] = bound['min_lon']
+      if bound['max_lat'] > boundary['max_lat']:
+        boundary['max_lat'] = bound['max_lat']
+      if bound['max_lon'] > boundary['max_lon']:
+        boundary['max_lon'] = bound['max_lon']
+    self.boundary = boundary
+  
+  def valMeasuredParameter(self,obj):
+    """Function to add ParameterName"""
+    valuesQAStats = []
+    valuesQAFlags = []
+    valuesParameter = []
+    for i in self.parModis:
+      valuesQAStats.append(i.retMeasure()['QAStats'])
+      valuesQAFlags.append(i.retMeasure()['QAFlags'])
+      valuesParameter.append(i.retMeasure()['ParameterName'])
+    for i in self._checkval(valuesParameter):
+      pn = self.ElementTree.SubElement(obj,'ParameterName')
+      pn.text = i
+  
+  def valInputPointer(self,obj):
+    """Function to add InputPointer"""
+    for i in self.parModis:
+      for v in i.retInputGranule():
+        ip = self.ElementTree.SubElement(obj,'InputPointer')
+        ip.text = v
+  
+  def valPlatform(self, obj):
+    """Function to add Platform tags"""
+    valuesSName = []
+    valuesInstr = []
+    valuesSensor = []
+    for i in self.parModis:
+        valuesSName.append(i.retPlatform()['PlatformShortName'])
+        valuesInstr.append(i.retPlatform()['InstrumentShortName'])
+        valuesSensor.append(i.retPlatform()['SensorShortName'])
+    for i in self._checkval(valuesSName):
+      pn = self.ElementTree.SubElement(obj,'PlatformShortName')
+      pn.text = i
+      
+    valInstr = self._checkval(valuesInstr)
+    valSens = self._checkval(valuesSensor)
+    
+    if len(valInstr) != len(valSens):
+      raise IOError('Something wrong reading XML files')
+    else:
+      for i in range(len(valInstr)):
+        ins = self.ElementTree.SubElement(obj,'Instrument')
+        pn = self.ElementTree.SubElement(ins,'InstrumentShortName')
+        pn.text = valInstr[i]
+        sens = self.ElementTree.SubElement(ins,'Sensor')
+        ps = self.ElementTree.SubElement(sens,'SensorShortName')
+        ps.text = valSens[i]
+
+  def writexml(self,outputname):
+    """Return a xml file for a mosaic"""
+    # the root element
+    granule = self.ElementTree.Element('GranuleMetaDataFile')
+    # add DTDVersion
+    self.valDTD(granule)
+    # add DataCenterId
+    self.valDataCenter(granule)
+    # add GranuleURMetaData
+    gurmd = self.ElementTree.SubElement(granule,'GranuleURMetaData')
+    # add GranuleUR
+    self.valGranuleUR(gurmd)
+    # add dbID
+    self.valDbID(gurmd)
+    
+    # TODO ADD InsertTime LastUpdate
+
+    # add CollectionMetaData
+    cmd = self.ElementTree.SubElement(gurmd,'CollectionMetaData')
+    self.valCollectionMetaData(cmd)
+    # add DataFiles
+    df = self.ElementTree.SubElement(gurmd,'DataFiles')
+    self.valDataFiles(df)
+    
+    # TODO ADD ECSDataGranule
+    
+    # add PGEVersionClass
+    pgevc = self.ElementTree.SubElement(gurmd,'PGEVersionClass')
+    self.valPGEVersion(pgevc)
+    # add RangeDateTime
+    rdt = self.ElementTree.SubElement(gurmd,'RangeDateTime')
+    self.valRangeTime(rdt)
+    # SpatialDomainContainer
+    sdc = self.ElementTree.SubElement(gurmd,'SpatialDomainContainer')
+    hsdc = self.ElementTree.SubElement(sdc,'HorizontalSpatialDomainContainer')
+    gp = self.ElementTree.SubElement(hsdc,'GPolygon')
+    bound = self.ElementTree.SubElement(gp,'Boundary')
+    self.valBound()
+    self._addPoint(bound,'min_lon','max_lat')
+    self._addPoint(bound,'max_lon','max_lat')
+    self._addPoint(bound,'min_lon','min_lat')
+    self._addPoint(bound,'max_lon','min_lat')
+    # add MeasuredParameter
+    mp = self.ElementTree.SubElement(gurmd,'MeasuredParameter')
+    mpc = self.ElementTree.SubElement(mp,'MeasuredParameterContainer')
+    self.valMeasuredParameter(mpc)
+    # Platform
+    pl = self.ElementTree.SubElement(gurmd,'Platform')
+    self.valPlatform(pl)
+
+    # add PSAs
+    psas = self.ElementTree.SubElement(gurmd,'PSAs')
+    # TODO ADD all PSA
+
+    # add InputGranule and InputPointer
+    ig = self.ElementTree.SubElement(gurmd,'InputGranule')
+    self.valInputPointer(ig)
+    # TODO ADD BrowseProduct
+    output = open(outputname, 'w')
+    output.write('<?xml version="1.0" encoding="UTF-8"?>')
+    output.write('<!DOCTYPE GranuleMetaDataFile SYSTEM "http://ecsinfo.gsfc.nasa.gov/ECSInfo/ecsmetadata/dtds/DPL/ECS/ScienceGranuleMetadata.dtd">')
+    output.write(self.ElementTree.tostring(granule))
+    output.close()

Added: grass-addons/grass7/grass7/raster/r.modis/libmodis/rmodislib.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/libmodis/rmodislib.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/libmodis/rmodislib.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,347 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+############################################################################
+#
+# MODULE:	r.modis
+# AUTHOR(S):	Luca Delucchi
+# PURPOSE:	Here there are some important class to run r.modis modules
+#
+#
+# COPYRIGHT:	(C) 2011 by Luca Delucchi
+#
+#		This program is free software under the GNU General Public
+#		License (>=v2). Read the file COPYING that comes with GRASS
+#		for details.
+#
+#############################################################################
+import grass.script as grass
+# interface to g.proj -p
+def get_proj():
+    """!Returns the output from running "g.proj -p" plus towgs84 parameter (g.proj -d), 
+    as a dictionary. Example:
+
+    \code
+    >>> proj = grass.get_proj()
+    >>> (proj['name'], proj['ellps'], proj['datum'])
+    (Lat/Lon, wgs84, wgs84)
+    \endcode
+
+    @return dictionary of projection values
+    """
+    gproj = grass.read_command('g.proj',flags='p')
+    listproj = gproj.split('\n')
+    listproj.remove('-PROJ_INFO-------------------------------------------------')
+    listproj.remove('-PROJ_UNITS------------------------------------------------')
+    listproj.remove('')
+    proj = {}
+    for i in listproj:
+        ilist = i.split(':')
+        proj[ilist[0].strip()] = ilist[1].strip()
+    proj.update(grass.parse_command('g.proj',flags='j'))
+    return proj
+
+class product:
+    """Definition of MODIS product with url and path in the ftp server
+    """
+    def __init__(self,value = None):
+        # url to download products
+        urlbase = 'e4ftl01.cr.usgs.gov'
+        usrsnow = 'n4ftl01u.ecs.nasa.gov'
+        ### values of lst product:
+        lst_spec = '( 1 0 0 0 1 0 0 0 0 0 0 0 )'
+        lst_specqa = '( 1 1 0 0 1 1 0 0 0 0 0 0 )'
+        # pattern for r.bitpatter (key is the pattern option, list of values 
+        #                         contain values for patval option)
+        lst_patt = {3 : [2, 3], 128 : [81, 85], 255 : [129, 133, 145, 149]}
+        # suffix for the lst product (key is the lst map, value the QA)
+        lst1km_suff = {'.LST_Day_1km':'.QC_Day','.LST_Night_1km':'.QC_Night'}
+        lst6km_suff = {'.LST_Day_6km':'.QC_Day','.LST_Night_6km':'.QC_Night'}
+        # color for lst product
+        lst_color = ['celsius']
+        ### values of vi product:
+        vi_spec = '( 1 1 0 0 0 0 0 0 0 0 0 )'
+        vi_specqa = '( 1 1 1 0 0 0 0 0 0 0 0 )'
+        vi_patt = {3 : [2, 3], 63 : [13, 14, 15], 128 : [3], 1024 : [1], 
+        8192 : [0, 6, 7], 16384 : [1], 32768 : [1]}
+        vi_color = ['ndvi','evi']
+        vi250m_suff = {'.250m_16_days_NDVI' : '.250m_16_days_VI_Quality',
+        '.250m_16_days_EVI' : '.250m_16_days_VI_Quality'}
+        vi500m_suff = {'.500m_16_days_NDVI' : '.500m_16_days_VI_Quality',
+        '.500m_16_days_EVI' : '.500m_16_days_VI_Quality'}        
+        vi1km_suff = {'.1_km_16_days_NDVI' : '.1_km_16_days_VI_Quality',
+        '.1_km_16_days_EVI' : '.1_km_16_days_VI_Quality'}
+        ### values of snow product:
+        snow1_spec = ('( 1 )')
+        snow1_specqa = ('( 1 1 )')
+        snow1_suff = {'.Snow_Cover_Daily_Tile':'.Snow_Spatial_QA'}
+        snow1_patt = {3 : [2,3], 7 : [6, 7], 15 : [10, 11, 14, 15]}
+        
+        snow8_spec = ('( 1 1 )')
+        snow_color = ['gyr'] #TODO CREATE THE COLOR TABLE FOR MODIS_SNOW
+        snow8_suff = {'.Maximum_Snow_Extent' : None, '.Eight_Day_Snow_Cover' : None}
+        lstL2_spec = 'LST; QC; Error_LST; Emis_31; Emis_32; View_angle; View_time'
+        
+	self.prod = value
+	lst = {'lst_aqua_daily_1000' : {'url' : urlbase, 'folder' : 'MOLA/MYD11A1.005',
+                                  'res' : 1000, 'spec' : lst_spec, 'spec_qa' : lst_specqa,
+                                  'suff' : lst1km_suff, 'pattern' : lst_patt, 
+                                  'color' : lst_color
+              },
+              'lst_terra_daily_1000' : {'url' : urlbase, 'folder' : 'MOLT/MOD11A1.005',
+                                  'res' : 1000, 'spec': lst_spec,'spec_qa': lst_specqa, 
+                                  'suff' : lst1km_suff, 'pattern' : lst_patt, 
+                                  'color' : lst_color
+              }, 
+              'lst_terra_eight_1000' : {'url' : urlbase, 'folder' : 'MOLT/MOD11A2.005',
+                                  'res' : 1000, 'spec': lst_spec,'spec_qa': lst_specqa, 
+                                  'suff' : lst1km_suff, 'pattern' : lst_patt, 
+                                  'color' : lst_color
+              },
+              'lst_aqua_eight_1000' : {'url' : urlbase, 'folder' : 'MOLA/MYD11A2.005',
+                                  'res' : 1000, 'spec': lst_spec,'spec_qa': lst_specqa, 
+                                  'suff' : lst1km_suff, 'pattern' : lst_patt, 
+                                  'color' : lst_color
+              },
+              'lst_terra_daily_6000' : {'url' : urlbase, 'folder' : 'MOLT/MOD11B1.005',
+                                  'res' : 6000, 'spec': lst_spec,'spec_qa': lst_specqa, 
+                                  'suff' : lst6km_suff, 'pattern' : lst_patt, 
+                                  'color' : lst_color
+              }, 
+              'lst_aqua_daily_6000' : {'url' : urlbase, 'folder' : 'MOLA/MYD11B1.005',
+                                  'res' : 6000, 'spec': lst_spec,'spec_qa': lst_specqa, 
+                                  'suff' : lst6km_suff, 'pattern' : lst_patt, 
+                                  'color' : lst_color
+              },
+
+        }
+	vi = {'ndvi_terra_sixteen_250':{'url':urlbase, 'folder':'MOLT/MOD13Q1.005',
+                                    'res':250,'spec': vi_spec,'spec_qa': vi_specqa,
+                                    'suff' : vi250m_suff, 'pattern' : vi_patt, 
+                                    'color' : vi_color
+              },
+              'ndvi_aqua_sixteen_250':{'url':urlbase, 'folder':'MOLA/MYD13Q1.005',
+                                    'res':250,'spec': vi_spec,'spec_qa': vi_specqa,
+                                    'suff' : vi250m_suff, 'pattern' : vi_patt, 
+                                    'color' : vi_color
+              },
+              'ndvi_terra_sixteen_500':{'url':urlbase, 'folder':'MOLT/MOD13A1.005',
+                                    'res':500,'spec': vi_spec,'spec_qa': vi_specqa,
+                                    'suff' : vi1km_suff, 'pattern' : vi_patt, 
+                                    'color' : vi_color
+              },
+              'ndvi_aqua_sixteen_500':{'url':urlbase, 'folder':'MOLA/MYD13A1.005',
+                                    'res':500,'spec': vi_spec,'spec_qa': vi_specqa,
+                                    'suff' : vi500m_suff, 'pattern' : vi_patt, 
+                                    'color' : vi_color
+              },
+              'ndvi_terra_sixteen_1000':{'url':urlbase, 'folder':'MOLT/MOD13A2.005',
+                                    'res':1000,'spec': vi_spec,'spec_qa': vi_specqa,
+                                    'suff' : vi500m_suff, 'pattern' : vi_patt, 
+                                    'color' : vi_color
+              },
+              'ndvi_aqua_sixteen_1000':{'url':urlbase, 'folder':'MOLA/MYD13A2.005',
+                                    'res':1000,'spec': vi_spec,'spec_qa': vi_specqa,
+                                    'suff' : vi1km_suff, 'pattern' : vi_patt, 
+                                    'color' : vi_color
+              }
+        }
+        snow = {'snow_terra_daily_500' : {'url' : usrsnow, 'folder' : 
+				'SAN/MOST/MOD10A1.005', 'res' : 500, 'spec' : snow1_spec
+				,'spec_qa': snow1_specqa, 'color' : snow_color,
+				'suff' : snow1_suff, 'pattern' : snow1_patt
+		}, 
+		'snow_aqua_daily_500' : {'url' : usrsnow, 'folder' : 
+                                'SAN/MOSA/MYD10A1.005', 'res' : 500, 'spec' : snow1_spec
+                                ,'spec_qa': snow1_specqa, 'color' : snow_color,
+                                'suff' : snow1_suff, 'pattern' : snow1_patt
+                },
+                'snow_terra_eight_500' : {'url' : usrsnow, 'folder' : 
+                                'SAN/MOST/MOD10A2.005', 'res' : 500, 'spec' : snow8_spec
+                                ,'spec_qa': None, 'color' : snow_color,
+                                'pattern' : None, 'suff' : snow8_suff
+                }, 
+                'snow_aqua_eight_500' : {'url' : usrsnow, 'folder' : 
+                                'SAN/MOSA/MYD10A2.005', 'res' : 500, 'spec' : snow8_spec
+                                ,'spec_qa': None, 'color' : snow_color,
+                                'pattern' : None, 'suff' : snow8_suff
+                }
+	}
+	self.products = { }
+	self.products.update(lst)
+	self.products.update(vi)
+	self.products.update(snow)
+        self.products_swath = { 
+          'lst_terra_daily':{'url':urlbase,'folder':'MOLT/MOD11_L2.005',
+          'spec': lstL2_spec}, 'lst_aqua_daily':{'url':urlbase,'folder':'MOLA/MYD11_L2.005',
+          'spec': lstL2_spec}
+        }
+    def returned(self):
+        if self.products.keys().count(self.prod) == 1:
+            return self.products[self.prod]
+        elif self.products_swath.keys().count(self.prod) == 1:
+            return self.products_swath[self.prod]
+        else:
+            grass.fatal(_("The code insert is not supported yet. Consider to ask " \
+                      + "on the grass-dev mailing list for future support"))
+
+    def fromcode(self,code):
+        import string
+        for k,v in self.products.iteritems():
+          if string.find(v['folder'],code) != -1:
+            return self.products[k]
+        for k,v in self.products_swath.iteritems():
+          if string.find(v['folder'],code) != -1:
+            return self.products_swath[k]
+        grass.fatal(_("The code insert is not supported yet. Consider to ask " \
+                      "on the grass-dev mailing list for future support"))
+
+    def color(self,code = None):
+        if code:
+          return self.fromcode(code)['color']
+        else:
+          return self.returned()['color']
+
+
+    def pattern(self,code = None):
+        if code:
+          return self.fromcode(code)['pattern']
+        else:
+          return self.returned()['pattern']
+
+    def suffix(self,code = None):
+        if code:
+          return self.fromcode(code)['suff']
+        else:
+          return self.returned()['suff']
+
+    def __str__(self):
+	prod = self.returned()
+	string = "url: " + prod['url'] + ", folder: " + prod['folder']
+        if prod.keys().count('spec') == 1:
+                string += ", spectral subset: " + prod['spec']
+        if prod.keys().count('spec_qa') == 1:
+                string += ", spectral subset qa:" + prod['spec_qa']
+	return string
+
+class resampling:
+    """Return the resampling value from the code used in the modules
+    """
+    def __init__(self,value):
+        self.code = value
+        self.resampling = {'nearest': 'NEAREST_NEIGHBOR', 'bilinear': 'BILINEAR',
+        'cubic': 'CUBIC CONVOLUTION'}
+
+    def returned(self):
+        return self.resampling[self.code]
+
+class projection:
+    """Definition of projection for converting from sinusoidal projection to
+    another one. Not all projection systems are supported"""
+    def __init__(self):
+        self.proj = get_proj()
+        self.val = self.proj['proj']
+        if self.proj['datum']:
+            self.dat = self.proj['datum']
+        else:
+            self.dat = 'none'
+        self.projections = {'laea' : 'LA','ll':'GEO', 'lcc':'LCC',
+             'merc':'MERCAT', 'polar':'PS', 'utm':'UTM', 'tmerc':'TM'}
+        self.datumlist = {'none':'NONE', 'nad27':'NAD27', 'nad83':'NAD83', 
+        'wgs66':'WGS66', 'wgs72':'WGS72', 'wgs84':'WGS84', 'etrs89':'WGS84'}
+        self.datumlist_swath = {'Clarke 1866' : 0, 'Clarke 1880' : 1, 'bessel' : 2,
+            'International 1967' : 3, 'International 1909': 4, 'wgs72' : 5, 
+            'Everest' : 6, 'wgs66' : 7, 'wgs84' : 8, 'Airy' : 9, 
+            'Modified Everest' : 10, 'Modified Airy' : 11, 'Walbeck' : 12, 
+            'Southeast Asia' : 13, 'Australian National' : 14, 'Krassovsky' : 15, 
+            'Hough' : 16, 'Mercury1960' : 17, 'Modified Mercury1968' : 18, 
+            'Sphere 19 (Radius 6370997)' : 19, 'MODIS Sphere (Radius 6371007.181)' : 20}
+
+    def returned(self):
+        """Return the projection in the MRT style"""
+        if self.val not in self.projections.keys():
+            grass.fatal(_("Projection <%s> is not supported") % self.val)
+        else:
+            return self.projections[self.val]
+
+    def _par(self,key):
+        """Function use in return_params"""
+        if self.proj[key]:
+            Val = self.proj[key]
+        else:
+            Val = 0.0
+        return float(Val)
+
+    def _outpar(self, SMajor, SMinor, Val, Factor, CentMer, TrueScale, FE, FN,swath):
+        if swath:
+          return '%i %i %d %d %d %d %d %d 0.0 0.0 0.0 0.0 0.0 0.0 0.0' % ( 
+                SMajor, SMinor, Val, Factor, CentMer, TrueScale, FE, FN )
+        else:
+          return '( %i %i %d %d %d %d %d %d 0.0 0.0 0.0 0.0 0.0 0.0 0.0 )' % ( 
+                SMajor, SMinor, Val, Factor, CentMer, TrueScale, FE, FN )
+
+    def return_params(self, swath = False):
+        """ Return the 13 parameters for MRT parameter file """
+        if self.val == 'll' or self.val == 'utm':
+            return self._outpar(0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, swath)
+        elif self.val == 'laea':
+            SMajor = self._par('+a')
+            try:
+                SMinor = self._par('+b')
+            except:
+                SMinor = self._par('+rf')
+            CentMer = self._par('+lon_0')
+            CentLat = self._par('+lat_0')
+            FE = self._par('+x_0')
+            FN = self._par('+y_0')
+            return self._outpar(SMajor, SMinor, 0.0, 0.0, CentMer, 
+                                CentLat, FE, FN, swath)
+        elif self.val == 'lcc':
+            SMajor = self._par('+a')
+            try:
+                SMinor = self._par('+b')
+            except:
+                SMinor = self._par('+rf')
+            STDPR1 = self._par('+lat_1')
+            STDPR2 = self._par('+lat_2')
+            CentMer = self._par('+lon_0')
+            CentLat = self._par('+lat_0')
+            FE = self._par('+x_0')
+            FN = self._par('+y_0')
+            return self._outpar(SMajor, SMinor, STDPR1, STDPR2, CentMer, 
+                                CentLat, FE, FN, swath)
+        elif self.val == 'merc' or self.val == 'polar' or self.val == 'tmerc':
+            SMajor = self._par('+a')
+            try:
+                SMinor = self._par('+b')
+            except:
+                SMinor = self._par('+rf')
+            CentMer = self._par('+lon_0')
+            if self.val == 'tmerc':
+                Factor = self._par('+k_0')
+            else:
+                Factor = 0.0
+            TrueScale = self._par('+lat_ts')
+            FE = self._par('+x_0')
+            FN = self._par('+y_0')
+            return self._outpar(SMajor, SMinor, 0.0, Factor, CentMer, 
+                                 TrueScale, FE, FN, swath)
+        else:
+            grass.fatal(_('Projection not supported, please contact the ' \
+                          'GRASS-dev mailing list'))
+
+    def datum(self):
+        """Return the datum in the MRT style"""
+        if self.dat not in self.datumlist.keys():
+            grass.fatal(_("Datum <%s> is not supported") % self.dat)
+        elif self.dat == 'etrs89':
+            grass.warning(_("Changing datum <%s> to <%s>") % (self.dat, 'wgs84'))
+        return self.datumlist[self.dat]
+
+    def datumswath(self):
+        """Return the datum in MRT style"""
+        return self.datumlist_swath[self.dat]
+
+    def utmzone(self):
+        """Return the utm zone number"""
+        return self.proj['zone']

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.download/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.download/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.download/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../../..
+
+PGM = r.modis.download
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script
+
+# $(ETC)/r.modis/r.modis.download/%: % | $(ETC)/r.modis/r.modis.download
+# 	$(INSTALL) $< $@
+# 
+# $(ETC)/r.modis/r.modis.download:
+# 	$(MKDIR) $@
\ No newline at end of file

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,78 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.modis.download</em> downloads selected MODIS products. The module
+can download several tiles at once and also multiple observation days
+for each MODIS product.
+
+<h2>NOTE</h2>
+
+The connection to the FTP data site requires a default login.
+To set the username and password options the user has to use
+the <em>setting</em> option; a file can be used (in this case the first
+line is the username, usually it is 'anonymous', in the second line
+the password is given, usually the user's e-mail address):
+<div class="code"><pre>
+  your_NASA_FTP_username
+  your_NASA_FTP_password
+</pre></div>
+As alternative, the user can pass the values from standard input.
+<p>
+
+<b>Warning</b>: The NASA policy does not permit to open more then ten
+connections in parallel with their FTP server. Hence no more than ten
+process of <em>r.modis.download</em> should run at the same time.
+<p>
+By default the downloaded files are stored in the path where the setting
+file is saved. The user can change this directory with <em>folder</em>
+option. The user has <!-- NOT?? --> to set the <em>folder</em> option if
+user and password are sent by standard input.
+<p>
+The time for the download depends on the number of requested tiles, days
+and the type of the MODIS product. For example, the NDVI product ranges 
+from 5 MB to 270 MB and the LST product ranges from 2 MB to 21 MB.
+
+<h2>EXAMPLES</h2>
+
+To download the MODIS LST product from the Terra satellite using the default
+options and setting the user and password by standard input, launch:
+<div class="code"><pre>
+r.modis.download setting=-
+</pre></div>
+
+Reading the user and password options from file:
+<div class="code"><pre>
+r.modis.download setting=/home/user/.grass7/r.modis/SETTING
+</pre></div>
+
+To download LST Terra product using the default options and changing
+the starting and ending dates to custom values:
+<div class="code"><pre>
+r.modis.download setting=/home/user/.grass7/r.modis/SETTING startday=2011-05-01 endday=2011-05-31
+</pre></div>
+
+To download another product (for example <em>Snow eight days 500 m</em>),
+with other default options:
+<div class="code"><pre>
+r.modis.download setting=/home/user/.grass7/r.modis/SETTING product=snow_terra_eight_500
+</pre></div>
+
+To use <em>r.modis.download</em> in a script with one of the other module
+the user has to set the <em>-g</em> flag to return the name of the file
+containing a list of downloaded HDF names:
+<div class="code"><pre>
+r.modis.download -g setting=/home/user/.grass7/r.modis/SETTING startday=2011-05-01 endday=2011-05-31
+</pre></div>
+
+<h2>SEE ALSO</h2>
+<em>
+<a href="r.modis.html">r.modis</a>,
+<a href="r.modis.import.html">r.modis.import</a>
+<!-- <a href="r.modis.process.html">r.modis.process</a>,-->
+</em>
+<a href="https://lpdaac.usgs.gov/lpdaac/products/modis_overview">Map of MODIS Land products' Sinusoidal grid tiling system</a> 
+
+<h2>AUTHOR</h2>
+
+Luca Delucchi, Google Summer of Code 2011
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.download/r.modis.download.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+############################################################################
+#
+# MODULE:        r.in.modis.download
+# AUTHOR(S):     Luca Delucchi
+# PURPOSE:       r.in.modis.download is an interface to pyModis for download 
+#                several tiles of MODIS produts from NASA ftp
+#
+# COPYRIGHT:        (C) 2011 by Luca Delucchi
+#
+#                This program is free software under the GNU General Public
+#                License (>=v2). Read the file COPYING that comes with GRASS
+#                for details.
+#
+#############################################################################
+
+#%module
+#% description: Download several tiles of MODIS products using pyModis
+#% keywords: raster
+#% keywords: import
+#%end
+#%flag
+#% key: d
+#% description: For debug mode, it will write more info in the log file
+#%end
+#%flag
+#% key: g
+#% description: Return the name of file containing the list of HDF tiles downloaded in shell script style
+#%end
+#%option
+#% key: settings
+#% type: string
+#% gisprompt: old,file,input
+#% label: Full path to settings file
+#% description: "-" to pass the parameter from stdin
+#% answer: -
+#% guisection: Define
+#%end
+#%option
+#% key: product
+#% type: string
+#% label: Name of MODIS product(s)
+#% multiple: yes
+#% required: no
+#% options: lst_terra_daily_1000, lst_aqua_daily_1000, lst_terra_eight_1000, lst_aqua_eight_1000, lst_terra_daily_6000, lst_aqua_daily_6000, ndvi_terra_sixteen_250, ndvi_aqua_sixteen_250, ndvi_terra_sixteen_500, ndvi_aqua_sixteen_500, snow_terra_daily_500, snow_aqua_daily_500, snow_terra_eight_500, snow_aqua_eight_500
+#% answer: lst_terra_daily_1000
+#%end
+#%option
+#% key: tiles
+#% type: string
+#% label: The name(s) of tile(s) to download (comma separated)
+#% description: e.g.: h18v04
+#% required: no
+#%end
+#%option
+#% key: startday
+#% type: string
+#% label: First date to download
+#% description: Format: YYYY-MM-DD. If not set the download starts from today and go back 10 days. If not endday the download stops 10 days after the endday
+#% required: no
+#%end
+#%option
+#% key: endday
+#% type: string
+#% label: Last date to download
+#% description: Format: YYYY-MM-DD. To use only together with startday
+#% required: no
+#%end
+#%option
+#% key: folder
+#% type: string
+#% label: Folder to store the downloaded data
+#% description: If not set, path of settings file is used
+#% required: no
+#%end
+
+# import library
+import os, sys
+from datetime import *
+import grass.script as grass
+
+# add the folder containing libraries to python path
+if os.path.isdir(os.path.join(os.getenv('GISBASE'), 'etc', 'r.modis',os.sep)):
+    libmodis = os.path.join(os.getenv('GISBASE'), 'etc', 'r.modis')
+elif os.path.isdir(os.path.join(os.getenv('GRASS_ADDON_PATH'), 'etc', 'r.modis',os.sep)):
+    libmodis = os.path.join(os.getenv('GRASS_ADDON_PATH'), 'etc', 'r.modis')
+else:
+    print "ERROR: path to libraries not found"
+    sys.exit()
+# try to import pymodis (modis) and some class for r.modis.download
+sys.path.append(libmodis)
+try:
+    from rmodislib import product
+    from downmodis import downModis
+except ImportError:
+    grass.fatal(_("modis library not imported"))
+
+def check(home):
+    """ Check if a folder it is writable by the user that launch the process
+    """
+    if os.access(home,os.W_OK):
+        return 1
+    else:
+        grass.fatal(_("Folder to write downloaded files does not" \
+        + " exist or is not writeable"))
+        return 0
+
+def checkdate(options):
+    """ Function to check the data and return the correct value to download the
+        the tiles
+    """
+    def check2day(second,first=None):
+        """Function to check two date"""
+        if not first:
+            valueDay = None
+            firstDay = date.today()
+        else:
+            valueDay = first
+            firstSplit = first.split('-')
+            firstDay = date(int(firstSplit[0]),int(firstSplit[1]),int(firstSplit[2]))
+        lastSplit = second.split('-')
+        lastDay = date(int(lastSplit[0]),int(lastSplit[1]),int(lastSplit[2]))
+        delta = firstDay-lastDay
+        valueDelta = int(delta.days)
+        return valueDay, second, valueDelta
+
+    # no set start and end day
+    if options['startday'] == '' and options['endday'] == '':
+        return None, None, 10
+    # set only end day
+    elif options['startday'] != '' and options['endday'] == '':
+        valueDelta = 10
+        valueEnd = options['startday']
+        firstSplit = valueEnd.split('-')
+        firstDay = date(int(firstSplit[0]),int(firstSplit[1]),int(firstSplit[2]))
+        delta = timedelta(10)
+        lastday = firstDay + delta
+        valueDay = lastday.strftime("%Y-%m-%d")
+    # set only start day
+    elif options['startday'] == '' and options['endday'] != '':
+        grass.fatal(_("It is not possible use <endday> option without <startday> option"))
+    # set start and end day
+    elif options['startday'] != '' and options['endday'] != '':
+        valueDay, valueEnd, valueDelta = check2day(options['startday'],options['endday'])
+    return valueDay, valueEnd, valueDelta 
+
+# main function
+def main():
+    # check if you are in GRASS
+    gisbase = os.getenv('GISBASE')
+    if not gisbase:
+        grass.fatal(_('$GISBASE not defined'))
+        return 0
+    # set username, password and folder if settings are insert by stdin
+    if options['settings'] == '-':
+        if options['folder'] != '':
+            if check(options['folder']):
+                fold = options['folder']
+            user = 'anonymous'
+            passwd = raw_input(_('Insert password (your e-mail): '))
+        else:
+            grass.fatal(_("Set folder parameter when using stdin for passing the username " \
+            + "and password"))
+            return 0
+    # set username, password and folder by file
+    else:
+        # open the file and read the the user and password:
+        # first line is username
+        # second line is password
+	if check(options['settings']):
+           filesett = open(options['settings'],'r')
+           fileread = filesett.readlines()
+           user = fileread[0].strip()
+           passwd = fileread[1].strip()
+           filesett.close()
+	else:
+	   grass.fatal(_("File <%s> not found") % options['settings'])
+        # set the folder by option folder
+        if options['folder'] != '':
+            if check(options['folder']):
+                fold = options['folder']
+        # set the folder from path where settings file is stored 
+        else:
+            path = os.path.split(options['settings'])[0]
+            if check(path):
+                fold = path
+    # check the version
+    version = grass.core.version()
+    # this is would be set automatically
+    if version['version'].find('7.') == -1:
+        grass.fatal(_('GRASS GIS version 7 required'))
+        return 0
+    # the product
+    products = options['product'].split(',')
+    # first date and delta
+    firstday, finalday, delta = checkdate(options)
+    # set tiles
+    if options['tiles'] == '':
+        tiles = None
+        grass.warning(_("Option 'tiles' not set. Downloading all available tiles"))
+    else:
+        tiles = options['tiles']
+    # set the debug
+    if flags['d']:
+        debug_opt = True
+    else:
+        debug_opt = False
+    for produ in products:
+        prod = product(produ).returned()
+        #start modis class
+      
+        modisOgg = downModis(url = prod['url'], user = user,password = passwd, 
+              destinationFolder = fold, tiles = tiles, path = prod['folder'], 
+              today = firstday, enddate = finalday, delta = delta, debug = debug_opt)
+        # connect to ftp
+        modisOgg.connectFTP()
+        if modisOgg.nconnection <= 20:
+            # download tha tiles
+            grass.message(_("Downloading MODIS product <%s>..." % produ))
+            modisOgg.downloadsAllDay()
+            filesize = int(os.path.getsize(modisOgg.filelist.name))
+            if flags['g'] and filesize != 0:
+                grass.message("filename=%s" % modisOgg.filelist.name)
+            elif flags['g'] and filesize == 0:
+                grass.message("filename=")
+            elif not flags['g'] and filesize == 0:
+                grass.message(_("All data have been previously downloaded"))
+            elif filesize != 0:
+                grass.message(_("All data have been downloaded, continue with "\
+                + "r.modis.import with the option 'files=%s'" % modisOgg.filelist.name \
+                + " and 'mrtpath=/path/to/mrt/'"))
+        else:
+            grass.fatal(_("Error during connection"))
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,129 @@
+<h2>DESCRIPTION</h2>
+
+The <em>r.modis</em> suite is a toolset to import MODIS satellite data in GRASS GIS. 
+It uses the <a href="http://gis.cri.fmach.it/development/pyModis">pyModis</a>
+library and the <a
+href="https://lpdaac.usgs.gov/lpdaac/tools/modis_reprojection_tool"> MODIS
+Reprojection Tool</a> software to convert, mosaik and process MODIS data.
+It requires the <a
+href="https://lpdaac.usgs.gov/lpdaac/tools/modis_reprojection_tool">MODIS
+Reprojection Tool</a> to be installed while <a
+href="http://gis.cri.fmach.it/development/pyModis">pyModis</a> is
+included in the <em>r.modis</em> suite.
+The suite offers three modules as interface with MODIS data. Each modules
+is dedicated to for a specific operation. The module <em>r.modis.download</em>
+is used to download MODIS HDF products from NASA FTP. These files can then
+be imported with <em>r.modis.import</em> which supports import of Level 3 
+MODIS products as single image or daily mosaik into GRASS GIS.
+<p>
+The user can download several MODIS products, by single or multiple tiles and
+also ranges of observation days retrieving data from the related NASA FTP server.
+<!--
+The suite process Level 2 data using the <em>r.modis.process</em> module.
+-->
+It imports Level 3 (georeferenced) products either as single image or as daily mosaik.
+
+<h4>Products</h4>
+The products already supported: 
+<ul>
+  <li><b>Land Surface Temperature daily 1 Km (Terra/Aqua)</b>: product provides per-pixel temperature
+      and emissivity values in a sequence of swath-based to grid-based global products.
+      The MODIS/Terra-Aqua LST/E Daily L3 Global 1 km Grid product (MOD11A1/MYD11A1), is tile-based 
+      and gridded in the Sinusoidal projection, and produced daily at 1 km spatial resolution. </li>
+  <li><b>Land Surface Temperature daily 6 Km (Terra/Aqua)</b>: data are composed from the daily 
+      1-kilometer LST product (MOD11A1/MYD11A1) and stored on a 1-km Sinusoidal grid as the 
+      average values of clear-sky LSTs during an 8-day period.<br>
+      MOD11A2/MYD11A2 is comprised of daytime and nighttime LSTs, quality assessment, 
+      observation times, view angles, bits of clear sky days and nights, and 
+      emissivities estimated in Bands 31 and 32 from land cover types.</li>
+  <li><b>Land Surface Temperature eight day 1 Km (Terra/Aqua)</b>: products provide per-pixel 
+      temperature and emissivity values in a sequence of swath-based to grid-based 
+      global products. The MODIS/Terra-Aqua LST/E Daily L3 Global 5 Km Grid 
+      (Short name: MOD11B1/MYD11B1), is tile-based and gridded in the Sinusoidal projection, 
+      and produced daily at 5 km spatial resolution.</li>
+  <li><b>VI sixteen days 250 m (Terra/Aqua)</b>: Global MODIS vegetation indices are designed 
+      to provide consistent spatial and temporal comparisons of vegetation conditions. 
+      Blue, red, and near-infrared reflectances, centered at 469-nanometers, 
+      645-nanometers, and 858-nanometers, respectively, are used to determine 
+      the MODIS daily vegetation indices.<br>
+      The MODIS Normalized Difference Vegetation Index (NDVI) complements NOAA's 
+      Advanced Very High Resolution Radiometer (AVHRR) NDVI products and provides 
+      continuity for time series historical applications. MODIS also includes a 
+      new Enhanced Vegetation Index (EVI) that minimizes canopy background variations 
+      and maintains sensitivity over dense vegetation conditions. The EVI also 
+      uses the blue band to remove residual atmosphere contamination caused by 
+      smoke and sub-pixel thin cloud clouds. The MODIS NDVI and EVI products are 
+      computed from atmospherically corrected bi-directional surface reflectances 
+      that have been masked for water, clouds, heavy aerosols, and cloud shadows.
+      Global MOD13Q1/MYD13Q1 data are provided every 16 days at 250-meter spatial resolution 
+      as a gridded level-3 product in the Sinusoidal projection. Lacking a 250m 
+      blue band, the EVI algorithm uses the 500m blue band to correct for residual 
+      atmospheric effects, with negligible spatial artifacts.</li>
+  <li><b>VI sixteen days 500 m (Terra/Aqua)</b>: Global MODIS vegetation indices are 
+      designed to provide consistent spatial and temporal comparisons of vegetation 
+      conditions. Blue, red, and near-infrared reflectances, centered at 
+      469-nanometers, 645-nanometers, and 858-nanometers, respectively, are used 
+      to determine the MODIS daily vegetation indices.<br>
+      The MODIS Normalized Difference Vegetation Index (NDVI) complements NOAA's 
+      Advanced Very High Resolution Radiometer (AVHRR) NDVI products provide 
+      continuity for time series historical applications. MODIS also includes a 
+      new Enhanced Vegetation Index (EVI) that minimizes canopy background 
+      variations and maintains sensitivity over dense vegetation conditions. 
+      The EVI also uses the blue band to remove residual atmosphere contamination 
+      caused by smoke and sub-pixel thin cloud clouds. The MODIS NDVI and EVI 
+      products are computed from atmospherically corrected bi-directional surface 
+      reflectances that have been masked for water, clouds, heavy aerosols, and 
+      cloud shadows.<br>
+      Global MOD13A1/MYD13A1 data are provided every 16 days at 500-meter spatial 
+      resolution as a gridded level-3 product in the Sinusoidal projection. 
+      Vegetation indices are used for global monitoring of vegetation conditions 
+      and are used in products displaying land cover and land cover changes. 
+      These data may be used as input for modeling global biogeochemical and 
+      hydrologic processes and global and regional climate. These data also may 
+      be used for characterizing land surface biophysical properties and processes, 
+      including primary production and land cover conversion.</li>
+  <li><b>Snow eight days 500 m (Terra/Aqua)</b>: The MOD10A2 and MYD10A2 products 
+      are composites of eight days of snow maps in the sinusoidal grid.
+      An eight-day compositing period was chosen because that is the exact ground 
+      track repeat period of the Terra and Aqua platforms. Snow cover over eight 
+      days is mapped as maximum snow extent in one SDS and as a chronology of 
+      observations in the other SDS. Eight-day periods begin on the first day of 
+      the year and extend into the next year. The product can be produced with 
+      two to eight days of input. There may not always be eight days of input, 
+      because of various reasons, so the user should check the attributes to 
+      determine on what days observations were obtained. See the validation webpage 
+      for details on the validation and validation definitions.</li>
+  <li><b>Snow daily 500 m (Terra/Aqua)</b>: MOD10A1 and MYD10A1 are tiles of daily 
+      snow cover at 500 m spatial resolution. The daily observation selected from 
+      multiple observations in a MOD10A1 (or MYD10A1) cell is the observation 
+      acquired nearest nadir and having the greatest coverage of the grid cell.
+      The daily MOD10A1 and MYD10A1 snow products are tiles of data gridded in the 
+      sinusoidal projection. Tiles are approximately 1200 x 1200 km in area. A 
+      single scientific data set (SDS) of snow cover and a single SDS of QA data 
+      along with local and global attributes comprise the data product file. The 
+      daily level 3 snow product is the result of selecting an observation from 
+      the multiple observations mapped to a cell of the MOD10_L2G (or MYD10_L2G) 
+      product. See the validation webpage for details on the validation and 
+      validation definitions.</li>
+</ul>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.modis.import.html">r.modis.import</a>,
+<a href="r.modis.download.html">r.modis.download</a>
+<!-- <a href="r.modis.process.html">r.modis.process</a>,-->
+</em>
+<p>
+<ul>
+ <li><a href="https://lpdaac.usgs.gov/lpdaac/tools/modis_reprojection_tool">MODIS Reprojection Tool</a></li>
+ <li> <a href="http://modis-land.gsfc.nasa.gov/index.htm">MODIS Land homepage</a></li>
+ <li> <a href="http://modis-snow-ice.gsfc.nasa.gov/">MODIS Snow homepage</a></li>
+ <li> <a href="https://lpdaac.usgs.gov/lpdaac/products/modis_products_table">MODIS Land products table</a></li>
+</ul>
+ 
+<h2>AUTHOR</h2>
+
+Luca Delucchi, Google Summer of Code 2011
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.import/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.import/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.import/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../../..
+
+PGM = r.modis.import
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script
+
+# $(ETC)/r.modis/r.modis.download/%: % | $(ETC)/r.modis/r.modis.download
+# 	$(INSTALL) $< $@
+# 
+# $(ETC)/r.modis/r.modis.download:
+# 	$(MKDIR) $@
\ No newline at end of file

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,73 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.modis.import</em> import into GRASS GIS Level 3 MODIS product.
+
+<h2>NOTE</h2>
+
+The input file is given as list of full paths to the MODIS HDF files,
+one per line. The input file(s) have to be inside the folder where 
+the HDF files are stored.
+<p>
+The <em>mrtpath</em> option is the path to the main folder of the
+MODIS Reprojection Tools (MRT) binaries, i.e. the folder which contains
+the bin/ and the data/ folder since these two folders are essential for
+obtaining a successful result.<br>
+It is not possible to use flag <em>--q</em> and the option <em>spectral</em>
+together.
+<p>
+
+<b>Warning</b>: 
+<ul>
+  <li>The module has currently only been tested with Lat/Long locations, but also
+   the following projection systems are supported: Lambert Azimuthal Equal Area,
+   Lambert Conformal Conic, Mercator, Polar Stereographic, Transverse Mercator,
+   Universal Transverse Mercator</li>
+</ul>
+
+<h2>EXAMPLES</h2>
+
+Import a single file with the default subset with QA layer analysis to remove bad pixels:
+<div class="code"><pre>
+r.modis.import dsn=/path/to/file mrtpath=/path/to/mrt
+</pre></div>
+
+Import more files with the default subset with QA layer:
+<div class="code"><pre>
+r.modis.import filename=/path/to/listfile mrtpath=/path/to/mrt
+</pre></div>
+
+Import more files like daily mosaic with the default subset without QA layer:
+<div class="code"><pre>
+r.modis.import filename=/path/to/listfile mrtpath=/path/to/mrt
+</pre></div>
+
+Import a single file with the default subset without QA layer analysis and without
+rescaling the pixel values:
+<div class="code"><pre>
+r.modis.import -r dsn=/path/to/file mrtpath=/path/to/mrt
+</pre></div>
+
+Import a single file with your own subset of layers (for power user):
+<div class="code"><pre>
+r.modis.import dsn=/path/to/file mrtpath=/path/to/mrt spectral="( 1 0 1 0 )"
+</pre></div>
+
+Import more files with your own subset of layers and without QA layer analysis (for power users):
+<div class="code"><pre>
+r.modis.import -q filename=/path/to/listfile mrtpath=/path/to/mrt spectral="( 1 )"
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.modis.html">r.modis</a>,
+<a href="r.modis.download.html">r.modis.download</a>
+<!-- <a href="r.modis.process.html">r.modis.process</a>,-->
+</em><br>
+<a href="https://lpdaac.usgs.gov/lpdaac/tools/modis_reprojection_tool">MODIS Reprojection Tool</a>
+ 
+<h2>AUTHOR</h2>
+
+Luca Delucchi, Google Summer of Code 2011
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.py
===================================================================
--- grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.py	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.modis/r.modis.import/r.modis.import.py	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,510 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+############################################################################
+#
+# MODULE:        r.modis.import
+# AUTHOR(S):     Luca Delucchi
+# PURPOSE:       r.modis.import is an interface to pyModis for import into GRASS
+#                GIS level 3 MODIS produts
+#
+# COPYRIGHT:        (C) 2011 by Luca Delucchi
+#
+#                This program is free software under the GNU General Public
+#                License (>=v2). Read the file COPYING that comes with GRASS
+#                for details.
+#
+#############################################################################
+#
+# REQUIREMENTS:
+#      -  MRT tools, https://lpdaac.usgs.gov/lpdaac/tools/modis_reprojection_tool
+#
+#############################################################################
+
+#%module
+#% description: Import single or multiple tiles of MODIS products using pyModis/MRT
+#% keywords: raster
+#% keywords: MODIS
+#%end
+#%flag
+#% key: m
+#% description: Create a mosaic for each day
+#%end
+#%flag
+#% key: t
+#% description: Preserve temporary files (TIF and HDF mosaic)
+#%end
+#%flag
+#% key: q
+#% description: Ignore the QA map layer, do not use with "r" flag
+#%end
+#%flag
+#% key: r
+#% description: Do not rescale the output map values to destination units
+#%end
+#%option
+#% key: mrtpath
+#% type: string
+#% key_desc: path
+#% description: Full path to MRT directory
+#% gisprompt: old,dir,input
+#% required: yes
+#%end
+#%option
+#% key: dns
+#% type: string
+#% key_desc: path
+#% description: Full path to single HDF file
+#% gisprompt: old,file,input
+#% required: no
+#%end
+#%option
+#% key: files
+#% type: string
+#% key_desc: file
+#% description: Full path to file with list of HDF files 
+#% gisprompt: old,file,input
+#% required: no
+#%end
+#%option G_OPT_R_OUTPUT
+#% required : no
+#% guisection: Import
+#%end
+#%option
+#% key: method
+#% type: string
+#% key_desc: resampling
+#% description: Code of spatial resampling method
+#% options: nearest, bilinear, cubic
+#% answer: nearest
+#% required: no
+#%end
+#%option
+#% key: spectral
+#% type: string
+#% key_desc: spectral subset
+#% description: String to choose subset of layers in HDF file for import 
+#% required: no
+#%end
+
+import os, sys, string, glob, shutil
+import grass.script as grass
+from datetime import date
+
+
+# add the folder containing libraries to python path
+if os.path.isdir(os.path.join(os.getenv('GISBASE'), 'etc', 'r.modis',os.sep)):
+    libmodis = os.path.join(os.getenv('GISBASE'), 'etc', 'r.modis')
+elif os.path.isdir(os.path.join(os.getenv('GRASS_ADDON_PATH'), 'etc', 'r.modis',os.sep)):
+    libmodis = os.path.join(os.getenv('GRASS_ADDON_PATH'), 'etc', 'r.modis')
+else:
+    print "ERROR: path to libraries not found"
+    sys.exit()
+
+sys.path.append(libmodis)
+# try to import pymodis (modis) and some classes for r.modis.download
+try:
+    from rmodislib import resampling, product, get_proj, projection
+except ImportError:
+    grass.fatal(_("rmodislib library not imported"))
+try:
+    from convertmodis  import convertModis, createMosaic
+except ImportError:
+    grass.fatal(_("convertmodis library not imported"))
+try:
+    from parsemodis import parseModis
+except ImportError:
+    grass.fatal(_("parsemodis library not imported"))    
+
+def list_files(opt, mosaik = False):
+    """If used in function single(): Return a list of HDF files from the file list
+    If used in function mosaic(): Return a dictionary with a list of HDF files for each day
+    """
+    # read the file with the list of HDF
+    if opt['files'] != '':
+        listoffile = open(opt['files'],'r')
+        basedir = os.path.split(listoffile.name)[0]
+        # if mosaic create a dictionary
+        if mosaik:
+            filelist = {}
+        # if not mosaic create a list
+        else:
+            filelist = []
+        # append hdf files
+        for line in listoffile:
+            if string.find(line,'xml') == -1 and mosaik == False:
+                filelist.append(line.strip())
+            # for mosaic create a list of hdf files for each day
+            elif string.find(line,'xml') == -1 and mosaik == True:
+                day = line.split('/')[-1].split('.')[1]
+                if filelist.has_key(day):
+                    filelist[day].append(line)
+                else:
+                    filelist[day] = [line]
+    # create a list for each file
+    elif options['dns'] != '':
+        filelist = [options['dns']]
+        basedir = os.path.split(filelist[0])[0]
+    return filelist, basedir
+
+def spectral(opts, prod, q, m = False):
+    """Return spectral string"""
+    # return the spectral set selected by the user
+    if opts['spectral'] != '':
+        spectr = opts['spectral']
+    # return the spectral by default
+    else:
+        if q:
+            if prod['spec_qa']:
+                spectr = prod['spec_qa']
+            else: 
+                spectr = prod['spec']
+        else:
+            spectr = prod['spec']
+        if m:
+            spectr = spectr.replace(' 0', '')
+    return spectr
+
+def confile(pm, opts, q, mosaik=False):
+    """Create the configuration file for MRT software"""
+    # return projection and datum 
+    projObj = projection()
+    proj = projObj.returned()
+    dat = projObj.datum()
+    if proj == 'UTM':
+        zone = projObj.utmzone()
+    else:
+        zone = None
+    cod = os.path.split(pm.hdfname)[1].split('.')[0]
+    prod = product().fromcode(cod)
+    if mosaik:
+        # if mosaic it remove all the 0 from the subset string to convert all 
+        # the right layer
+        spectr = spectral(opts, prod, q, True)
+    else:
+        spectr = spectral(opts, prod, q)
+    # out prefix
+    pref = prefix(opts)
+    # resampling
+    resampl = resampling(opts['method']).returned()
+    # projpar
+    projpar = projObj.return_params()
+    if projpar != "( 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 )":
+        dat = "NODATUM"
+    # resolution
+    if proj != 'GEO':
+        res = int(prod['res']) * int(projObj.proj['meters'])
+    else:
+        res = None
+    try:
+        conf = pm.confResample(spectr, res, pref, dat, resampl, 
+                                proj, zone, projpar)
+        return conf
+    except IOError, e:
+        grass.fatal(e)
+
+def prefix(options, name = False):
+    """Return the prefix of output file if not set return None to use default
+       value
+    """
+    if options['output']:
+        return options['output']
+    else:
+        return None  
+
+def import_tif(out, basedir, rem, write, target=None):
+    """Import TIF files"""
+    # list of tif files
+    tifiles = glob.glob1(basedir, out + "*.tif")
+    if not tifiles:
+        grass.fatal(_('Error during the conversion'))
+    # check if user is in latlong location to set flag l
+    if projection().val == 'll':
+        f = "l"
+    else:
+        f = None
+    outfile = []
+    # for each file import it
+    for t in tifiles:
+        basename = os.path.splitext(t)[0]
+        name = os.path.join(basedir,t)
+        filesize = int(os.path.getsize(name))
+        if filesize < 1000:
+            grass.warning(_('Probably some error occur during the conversion' \
+            + 'for file <%s>. Escape import' % name))
+            continue
+        try:
+            grass.run_command('r.in.gdal', input = name, output = basename,
+                              flags = f, overwrite = write, quiet = True)
+            outfile.append(basename)
+        except:
+            grass.fatal(_('Error during import'))
+        if rem:
+            os.remove(name)
+        if target: 
+            if target != basedir:
+                shutil.move(name,target)
+    return outfile
+
+def findfile(pref, suff):
+    """ Check if a file exists on mapset """
+    if grass.find_file(pref + suff)['file']:
+        return grass.find_file(pref + suff)
+    else:
+        grass.warning(_("Raster map <%s> not found") % (pref + suff))
+
+def metadata(pars, mapp, coll):
+    """ Set metadata to the imported files """
+    # metadata
+    meta = pars.metastring()
+    grass.run_command('r.support', quiet = True, map=mapp, hist=meta)
+    # timestamp
+    rangetime = pars.retRangeTime()
+    data = rangetime['RangeBeginningDate'].split('-')
+    dataobj = date(int(data[0]),int(data[1]),int(data[2]))
+    grass.run_command('r.timestamp', map=mapp, date=dataobj.strftime("%d %b %Y"),
+                      quiet = True)
+    # color
+    if string.find(mapp, 'QC') != -1 or string.find(mapp, 'Quality') != -1 or \
+    string.find(mapp, 'QA') != -1:
+        grass.run_command('r.colors', quiet = True, map=mapp, color = coll)
+    elif string.find(mapp, 'NDVI') != -1:
+        grass.run_command('r.colors', quiet = True, map=mapp, color = coll[0])
+    elif string.find(mapp, 'EVI') != -1:
+        grass.run_command('r.colors', quiet = True, map=mapp, color = coll[1])
+    elif string.find(mapp, 'LST') != -1:
+        grass.run_command('r.colors', quiet = True, map=mapp, color = coll[0])
+    elif string.find(mapp, 'Snow') != -1:
+        grass.run_command('r.colors', quiet = True, map=mapp, color = coll[0])
+
+def analyze(pref, an, cod, parse, write):
+    """ Analyze the MODIS data using QA if present """
+    prod = product().fromcode(cod)
+    if not prod['spec_qa']:
+        grass.warning(_("There is no QA layer, analysis and filtering will be skipped"))
+        an = 'noqa'
+    pat = prod['pattern']
+    suf = prod['suff']
+    col = prod['color']
+    val = []
+    qa = []
+    for v,q in suf.iteritems():
+        val.append(findfile(pref,v))
+        if q:
+            qa.append(findfile(pref,q))
+    for n in range(len(val)):
+        if val[n] == None:
+            grass.warning(_("Some error occur"))
+            continue
+        valname = val[n]['name']
+        valfull = val[n]['fullname']
+        grass.run_command('g.region', rast = valfull)
+        grass.run_command('r.null', map = valfull, setnull = 0)
+        if string.find(cod,'13Q1') >= 0 or string.find(cod,'13A2') >= 0:
+            mapc = "%s.2 = %s / 10000." % (valname, valfull)
+        elif string.find(cod,'11A1') >= 0 or string.find(cod,'11A2') >= 0 or string.find(cod,'11B1') >= 0:
+            mapc = "%s.2 = (%s * 0.0200) - 273.15" % (valname, valfull)
+        grass.mapcalc(mapc)
+        if an == 'noqa':
+            #grass.run_command('g.remove', quiet = True, rast = valfull)
+            try:
+                grass.run_command('g.rename', quiet = True, overwrite = write, 
+                                rast=(valname,valname + '.orig'))
+                grass.run_command('g.rename', quiet = True, overwrite = write, 
+                                rast= (valname + '.2', valname))
+            except:
+                pass
+            metadata(parse, valname, col)
+            metadata(parse, valname, col)
+            metadata(parse, qafull, 'byr')
+        if an == 'all':
+            if len(qa) != len(val):
+                grass.fatal(_("The number of QA and value maps is different, something is wrong"))
+            qaname = qa[n]['name']
+            qafull = qa[n]['fullname']
+            finalmap = "%s.3=if(" % valname
+            first_map = 1
+            for key,value in prod['pattern'].iteritems():
+                for v in value:
+                    outpat = "%s.%i.%i" % (qaname, key, v)
+                    grass.run_command('r.bitpattern', quiet = True, input = qafull, 
+                                    output = outpat, pattern = key, patval= v)
+                    if first_map:
+                        first_map = 0
+                        finalmap += "%s == 0 " % outpat
+                    else:
+                        finalmap += "&& %s == 0 " % outpat
+
+            if string.find(cod,'13Q1') >= 0 or string.find(cod,'13A2') >= 0:
+                    finalmap += "&& %s.2 <= 1.000" % valname
+            finalmap += ",%s.2, null() )" % valname
+            # grass.message("mapc finalmap: %s" % finalmap)
+            grass.mapcalc(finalmap)
+            #grass.run_command('g.remove', quiet = True, rast=(valname, valname + '.2'))
+            grass.run_command('g.rename', quiet = True, overwrite = write, 
+			      rast=(valname,valname + '.orig'))
+            grass.run_command('g.remove', quiet = True, rast=(valname + '.2'))
+            grass.run_command('g.mremove', flags="f", quiet = True,
+			      rast = ("%s.*" % qaname))
+            grass.run_command('g.rename', quiet = True, overwrite = write,
+                              rast=(valname + '.3', valname))
+            metadata(parse, valname, col)
+            metadata(parse, valname, col)
+            metadata(parse, qafull, 'byr')
+
+def single(options,remove,an,ow):
+    """Convert the HDF file to TIF and import it
+    """
+    listfile, basedir = list_files(options)
+    pid = str(os.getpid())
+    # for each file
+    for i in listfile:
+        # the full path to hdf file
+        hdf = os.path.join(basedir,i)
+        # create conf file fro mrt tools
+        pm = parseModis(hdf)
+        confname = confile(pm,options,an)
+        print confname
+        # create convertModis class and convert it in tif file
+        execmodis = convertModis(hdf,confname,options['mrtpath'])
+        execmodis.run()
+        output = prefix(options)
+        if not output:
+            output = os.path.split(hdf)[1].rstrip('.hdf')
+        # import tif files
+        maps_import = import_tif(output,basedir,remove,ow)
+        if an and len(maps_import) != 0:
+            grass.run_command('g.region', save = 'oldregion.%s' % pid)
+            try:
+                cod = os.path.split(pm.hdfname)[1].split('.')[0]
+                analyze(outname, an, cod, pm, ow)
+            except:
+                grass.run_command('g.region', region = 'oldregion.%s' % pid)
+                grass.run_command('g.remove',quiet = True, 
+                    region = 'oldregion.%s' % pid)
+            cod = os.path.split(pm.hdfname)[1].split('.')[0]
+            analyze(output, an, cod, pm, ow)
+        #os.remove(confname)
+
+def mosaic(options,remove,an,ow):
+    """Create a daily mosaic of HDF files convert to TIF and import it
+    """
+    dictfile, targetdir = list_files(options,True)
+    pid = str(os.getpid())
+    # for each day
+    for dat, listfiles in dictfile.iteritems():
+        # create the file with the list of name
+        tempfile = open(os.path.join(targetdir,pid),'w')
+        tempfile.writelines(listfiles)
+        tempfile.close()
+        # basedir of tempfile, where hdf files are write
+        basedir = os.path.split(tempfile.name)[0]
+        outname = "%s.%s.mosaic" % (listfiles[0].split('/')[-1].split('.')[0],
+                                    listfiles[0].split('/')[-1].split('.')[1])
+        # return the spectral subset in according mrtmosaic tool format
+        prod = product().fromcode(listfiles[0].split('/')[-1].split('.')[0])
+        spectr = spectral(options,prod,an)
+        spectr = spectr.lstrip('( ').rstrip(' )')
+        # create mosaic
+        cm = createMosaic(tempfile.name, outname, options['mrtpath'], spectr)
+        cm.run()
+        # list of hdf files
+        hdfiles = glob.glob1(basedir, outname + "*.hdf")
+        for i in hdfiles:
+            # the full path to hdf file
+            hdf = os.path.join(basedir,i)
+            # create conf file fro mrt tools
+            pm = parseModis(hdf)
+            confname = confile(pm,options,an, True)
+            # create convertModis class and convert it in tif file
+            execmodis = convertModis(hdf, confname, options['mrtpath'])
+            execmodis.run()
+            # remove hdf 
+            if remove:  
+                # import tif files
+                maps_import = import_tif(outname, basedir, remove, ow)
+                if an:
+                    grass.run_command('g.region', save = 'oldregion.%s' % pid)
+                    try:
+                        cod = os.path.split(pm.hdfname)[1].split('.')[0]
+                        analyze(outname, an, cod, pm, ow)
+                    except:
+                        grass.run_command('g.region', region = 'oldregion.%s' % pid)
+                        grass.run_command('g.remove',quiet = True,
+				    region = 'oldregion.%s' % pid)
+                os.remove(hdf)
+                os.remove(hdf + '.xml')
+            # or move the hdf and hdf.xml to the dir where are the original files
+            else:
+                # import tif files
+                import_tif(outname, basedir, remove, ow, targetdir)
+                if an and len(maps_import) != 0:
+                    grass.run_command('g.region', save = 'oldregion.%s' % pid)
+                    try:
+                        cod = os.path.split(pm.hdfname)[1].split('.')[0]
+                        analyze(outname, an, cod, pm, ow)
+                    except:
+                        grass.run_command('g.region', region = 'oldregion.%s' % pid)
+                        grass.run_command('g.remove', region = 'oldregion.%s' % pid)
+                try: 
+                    shutil.move(hdf,targetdir)
+                    shutil.move(hdf + '.xml',targetdir)
+                except:
+                    pass
+            # remove the conf file
+            os.remove(confname)
+        grass.try_remove(tempfile.name)
+        grass.try_remove(os.path.join(targetdir,'mosaic',pid))
+
+def main():
+    # check if you are in GRASS
+    gisbase = os.getenv('GISBASE')
+    if not gisbase:
+        grass.fatal(_('$GISBASE not defined'))
+        return 0
+    # return an error if q and spectral are set
+    if not flags['q'] and options['spectral'] != '':
+        grass.warning(_('If no QA layer chosen in the "spectral" option'\
+        + 'the command will report an error'))
+    # return an error if both dns and files option are set or not
+    if options['dns'] == '' and options['files'] == '':
+        grass.fatal(_('Choose one of "dns" or "files" options'))
+        return 0
+    elif options['dns'] != '' and options['files'] != '':
+        grass.fatal(_('It is not possible set "dns" and "files" options together'))
+        return 0
+    # check the version
+    version = grass.core.version()
+    # this is would be set automatically
+    if version['version'].find('7.') == -1:
+        grass.fatal(_('GRASS GIS version 7 required'))
+        return 0
+    # check if remove the files or not
+    if flags['t']:
+        remove = False
+    else:
+        remove = True
+    if grass.overwrite():
+        over = True
+    else:
+        over = False
+    # check if do check quality, rescaling and setting of colors
+    if flags['r']:
+        analyze = None
+    elif flags['q']:
+        analyze = 'noqa'
+    else:
+        analyze = 'all'
+    # check if import simple file or mosaic
+    if flags['m'] and options['dns'] != '':
+        grass.fatal(_('It is not possible to create a mosaic with a single HDF file'))
+        return 0
+    elif flags['m']:
+        mosaic(options,remove,analyze,over)
+    else:
+        single(options,remove,analyze,over)
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())
+

Added: grass-addons/grass7/grass7/raster/r.regression.multi/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.regression.multi/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.regression.multi/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.regression.multi
+
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.regression.multi/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.regression.multi/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.regression.multi/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,571 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.regression.multi
+ * 
+ * AUTHOR(S):    Markus Metz
+ * 
+ * PURPOSE:      Calculates multiple linear regression from raster maps:
+ *               y = b0 + b1*x1 + b2*x2 + ... +  bn*xn + e
+ * 
+ * COPYRIGHT:    (C) 2011 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/raster.h>
+
+struct MATRIX
+{
+    int n;			/* SIZE OF THIS MATRIX (N x N) */
+    double *v;
+};
+
+#define M(m,row,col) (m)->v[((row) * ((m)->n)) + (col)]
+
+static int solvemat(struct MATRIX *m, double a[], double B[])
+{
+    int i, j, i2, j2, imark;
+    double factor, temp;
+    double pivot;		/* ACTUAL VALUE OF THE LARGEST PIVOT CANDIDATE */
+
+    for (i = 0; i < m->n; i++) {
+	j = i;
+
+	/* find row with largest magnitude value for pivot value */
+
+	pivot = M(m, i, j);
+	imark = i;
+	for (i2 = i + 1; i2 < m->n; i2++) {
+	    temp = fabs(M(m, i2, j));
+	    if (temp > fabs(pivot)) {
+		pivot = M(m, i2, j);
+		imark = i2;
+	    }
+	}
+
+	/* if the pivot is very small then the points are nearly co-linear */
+	/* co-linear points result in an undefined matrix, and nearly */
+	/* co-linear points results in a solution with rounding error */
+
+	if (pivot == 0.0) {
+	    G_warning(_("Matrix is unsolvable"));
+	    return 0;
+	}
+
+	/* if row with highest pivot is not the current row, switch them */
+
+	if (imark != i) {
+	    for (j2 = 0; j2 < m->n; j2++) {
+		temp = M(m, imark, j2);
+		M(m, imark, j2) = M(m, i, j2);
+		M(m, i, j2) = temp;
+	    }
+
+	    temp = a[imark];
+	    a[imark] = a[i];
+	    a[i] = temp;
+	}
+
+	/* compute zeros above and below the pivot, and compute
+	   values for the rest of the row as well */
+
+	for (i2 = 0; i2 < m->n; i2++) {
+	    if (i2 != i) {
+		factor = M(m, i2, j) / pivot;
+		for (j2 = j; j2 < m->n; j2++)
+		    M(m, i2, j2) -= factor * M(m, i, j2);
+		a[i2] -= factor * a[i];
+	    }
+	}
+    }
+
+    /* SINCE ALL OTHER VALUES IN THE MATRIX ARE ZERO NOW, CALCULATE THE
+       COEFFICIENTS BY DIVIDING THE COLUMN VECTORS BY THE DIAGONAL VALUES. */
+
+    for (i = 0; i < m->n; i++) {
+	B[i] = a[i] / M(m, i, i);
+    }
+
+    return 1;
+}
+
+int main(int argc, char *argv[])
+{
+    unsigned int r, c, rows, cols, n_valid;	/*  totals  */
+    int *mapx_fd, mapy_fd, mapres_fd, mapest_fd;
+    int i, j, k, n_predictors;
+    double *sumX, sumY, *sumsqX, sumsqY, *sumXY;
+    double *meanX, meanY, *varX, varY, *sdX, sdY;
+    double yest, yres;       /* estimated y, residual */
+    double sumYest, *SSerr_without;
+    double SE;
+    double meanYest, meanYres, varYest, varYres, sdYest, sdYres;
+    double SStot, SSerr, SSreg;
+    double **a;
+    struct MATRIX *m, *m_all;
+    double **B, Rsq, Rsqadj, F, t, AIC, AICc, BIC;
+    unsigned int count = 0;
+    DCELL **mapx_buf, *mapy_buf, *mapx_val, mapy_val, *mapres_buf, *mapest_buf;
+    char *name;
+    struct Option *input_mapx, *input_mapy, *output_res, *output_est, *output_opt;
+    struct Flag *shell_style;
+    struct Cell_head region;
+    struct GModule *module;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("statistics"));
+    module->description =
+	_("Calculates multiple linear regression from raster maps.");
+
+    /* Define the different options */
+    input_mapx = G_define_standard_option(G_OPT_R_INPUTS);
+    input_mapx->key = "mapx";
+    input_mapx->description = (_("Map for x coefficient"));
+
+    input_mapy = G_define_standard_option(G_OPT_R_INPUT);
+    input_mapy->key = "mapy";
+    input_mapy->description = (_("Map for y coefficient"));
+
+    output_res = G_define_standard_option(G_OPT_R_OUTPUT);
+    output_res->key = "residuals";
+    output_res->required = NO;
+    output_res->description = (_("Map to store residuals"));
+
+    output_est = G_define_standard_option(G_OPT_R_OUTPUT);
+    output_est->key = "estimates";
+    output_est->required = NO;
+    output_est->description = (_("Map to store estimates"));
+
+    output_opt = G_define_standard_option(G_OPT_F_OUTPUT);
+    output_opt->key = "output";
+    output_opt->required = NO;
+    output_opt->description =
+	(_("ASCII file for storing regression coefficients (output to screen if file not specified)."));
+
+    shell_style = G_define_flag();
+    shell_style->key = 'g';
+    shell_style->description = _("Print in shell script style");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    name = output_opt->answer;
+    if (name != NULL && strcmp(name, "-") != 0) {
+	if (NULL == freopen(name, "w", stdout)) {
+	    G_fatal_error(_("Unable to open file <%s> for writing"), name);
+	}
+    }
+
+    G_get_window(&region);
+    rows = region.rows;
+    cols = region.cols;
+
+    /* count x maps */
+    for (i = 0; input_mapx->answers[i]; i++);
+    n_predictors = i;
+    
+    /* allocate memory for x maps */
+    mapx_fd = (int *)G_malloc(n_predictors * sizeof(int));
+    sumX = (double *)G_malloc(n_predictors * sizeof(double));
+    sumsqX = (double *)G_malloc(n_predictors * sizeof(double));
+    sumXY = (double *)G_malloc(n_predictors * sizeof(double));
+    SSerr_without = (double *)G_malloc(n_predictors * sizeof(double));
+    meanX = (double *)G_malloc(n_predictors * sizeof(double));
+    varX = (double *)G_malloc(n_predictors * sizeof(double));
+    sdX = (double *)G_malloc(n_predictors * sizeof(double));
+    mapx_buf = (DCELL **)G_malloc(n_predictors * sizeof(DCELL *));
+    mapx_val = (DCELL *)G_malloc((n_predictors + 1) * sizeof(DCELL));
+    
+    /* ordinary least squares */
+    m = NULL;
+    m_all = (struct MATRIX *)G_malloc((n_predictors + 1) * sizeof(struct MATRIX));
+    a = (double **)G_malloc((n_predictors + 1) * sizeof(double *));
+    B = (double **)G_malloc((n_predictors + 1) * sizeof(double *));
+
+    m = &(m_all[0]);
+    m->n = n_predictors + 1;
+    m->v = (double *)G_malloc(m->n * m->n * sizeof(double));
+
+    a[0] = (double *)G_malloc(m->n * sizeof(double));
+    B[0] = (double *)G_malloc(m->n * sizeof(double));
+
+    for (i = 0; i < m->n; i++) {
+	for (j = i; j < m->n; j++)
+	    M(m, i, j) = 0.0;
+	a[0][i] = 0.0;
+	B[0][i] = 0.0;
+    }
+    
+    for (k = 1; k <= n_predictors; k++) {
+	m = &(m_all[k]);
+	m->n = n_predictors;
+	m->v = (double *)G_malloc(m->n * m->n * sizeof(double));
+	a[k] = (double *)G_malloc(m->n * sizeof(double));
+	B[k] = (double *)G_malloc(m->n * sizeof(double));
+
+	for (i = 0; i < m->n; i++) {
+	    for (j = i; j < m->n; j++)
+		M(m, i, j) = 0.0;
+	    a[k][i] = 0.0;
+	    B[k][i] = 0.0;
+	}
+    }
+
+    /* open maps */
+    G_debug(1, "open maps");
+    for (i = 0; i < n_predictors; i++) {
+	mapx_fd[i] = Rast_open_old(input_mapx->answers[i], "");
+    }
+    mapy_fd = Rast_open_old(input_mapy->answer, "");
+
+    for (i = 0; i < n_predictors; i++)
+	mapx_buf[i] = Rast_allocate_d_buf();
+    mapy_buf = Rast_allocate_d_buf();
+
+    for (i = 0; i < n_predictors; i++) {
+	sumX[i] = sumsqX[i] = sumXY[i] = 0.0;
+	meanX[i] = varX[i] = sdX[i] = 0.0;
+	SSerr_without[i] = 0.0;
+    }
+    sumY = sumsqY = meanY = varY = sdY = 0.0;
+    sumYest = meanYest = varYest = sdYest = 0.0;
+    meanYres = varYres = sdYres = 0.0;
+
+    /* read input maps */
+    G_message(_("First pass..."));
+    n_valid = 0;
+    mapx_val[0] = 1.0;
+    for (r = 0; r < rows; r++) {
+	G_percent(r, rows, 2);
+
+	for (i = 0; i < n_predictors; i++)
+	    Rast_get_d_row(mapx_fd[i], mapx_buf[i], r);
+
+	Rast_get_d_row(mapy_fd, mapy_buf, r);
+
+	for (c = 0; c < cols; c++) {
+	    int isnull = 0;
+
+	    for (i = 0; i < n_predictors; i++) {
+		mapx_val[i + 1] = mapx_buf[i][c];
+		if (Rast_is_d_null_value(&(mapx_val[i + 1]))) {
+		    isnull = 1;
+		    break;
+		}
+	    }
+	    if (isnull)
+		continue;
+
+	    mapy_val = mapy_buf[c];
+	    if (Rast_is_d_null_value(&mapy_val))
+		continue;
+
+	    for (i = 0; i <= n_predictors; i++) {
+		double val1 = mapx_val[i];
+
+		for (j = i; j <= n_predictors; j++) {
+		    double val2 = mapx_val[j];
+
+		    m = &(m_all[0]);
+		    M(m, i, j) += val1 * val2;
+
+		    /* linear model without predictor k */
+		    for (k = 1; k <= n_predictors; k++) {
+			if (k != i && k != j) {
+			    int i2 = k > i ? i : i - 1;
+			    int j2 = k > j ? j : j - 1;
+
+			    m = &(m_all[k]);
+			    M(m, i2, j2) += val1 * val2;
+			}
+		    }
+		}
+
+		a[0][i] += mapy_val * val1;
+		for (k = 1; k <= n_predictors; k++) {
+		    if (k != i) {
+			int i2 = k > i ? i : i - 1;
+
+			a[k][i2] += mapy_val * val1;
+		    }
+		}
+
+		if (i > 0) {
+		    sumX[i - 1] += val1;
+		    sumsqX[i - 1] += val1 * val1;
+		    sumXY[i - 1] += val1 * mapy_val;
+		}
+	    }
+
+	    sumY += mapy_val;
+	    sumsqY += mapy_val * mapy_val;
+	    count++;
+	}
+    }
+    G_percent(rows, rows, 2);
+    
+    if (count < n_predictors + 1)
+	G_fatal_error(_("Not enough valid cells available"));
+
+    for (k = 0; k <= n_predictors; k++) {
+	m = &(m_all[k]);
+
+	/* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
+	for (i = 1; i < m->n; i++)
+	    for (j = 0; j < i; j++)
+		M(m, i, j) = M(m, j, i);
+
+	if (!solvemat(m, a[k], B[k])) {
+	    for (i = 0; i <= n_predictors; i++) {
+		fprintf(stdout, "b%d=0.0\n", i);
+	    }
+	    G_fatal_error(_("Multiple regression failed"));
+	}
+    }
+    
+    /* second pass */
+    G_message(_("Second pass..."));
+
+    /* residuals output */
+    if (output_res->answer) {
+	mapres_fd = Rast_open_new(output_res->answer, DCELL_TYPE);
+	mapres_buf = Rast_allocate_d_buf();
+    }
+    else {
+	mapres_fd = -1;
+	mapres_buf = NULL;
+    }
+
+    /* estimates output */
+    if (output_est->answer) {
+	mapest_fd = Rast_open_new(output_est->answer, DCELL_TYPE);
+	mapest_buf = Rast_allocate_d_buf();
+    }
+    else {
+	mapest_fd = -1;
+	mapest_buf = NULL;
+    }
+
+    for (i = 0; i < n_predictors; i++)
+	meanX[i] = sumX[i] / count;
+
+    meanY = sumY / count;
+    SStot = SSerr = SSreg = 0.0;
+    for (r = 0; r < rows; r++) {
+	G_percent(r, rows, 2);
+
+	for (i = 0; i < n_predictors; i++)
+	    Rast_get_d_row(mapx_fd[i], mapx_buf[i], r);
+
+	Rast_get_d_row(mapy_fd, mapy_buf, r);
+	
+	if (mapres_buf)
+	    Rast_set_d_null_value(mapres_buf, cols);
+	if (mapest_buf)
+	    Rast_set_d_null_value(mapest_buf, cols);
+
+	for (c = 0; c < cols; c++) {
+	    int isnull = 0;
+
+	    for (i = 0; i < n_predictors; i++) {
+		mapx_val[i + 1] = mapx_buf[i][c];
+		if (Rast_is_d_null_value(&(mapx_val[i + 1]))) {
+		    isnull = 1;
+		    break;
+		}
+	    }
+	    if (isnull)
+		continue;
+
+	    yest = 0.0;
+	    for (i = 0; i <= n_predictors; i++) {
+		yest += B[0][i] * mapx_val[i];
+	    }
+	    if (mapest_buf)
+		mapest_buf[c] = yest;
+
+	    mapy_val = mapy_buf[c];
+	    if (Rast_is_d_null_value(&mapy_val))
+		continue;
+
+	    yres = mapy_val - yest;
+	    if (mapres_buf)
+		mapres_buf[c] = yres;
+
+	    SStot += (mapy_val - meanY) * (mapy_val - meanY);
+	    SSreg += (yest - meanY) * (yest - meanY);
+	    SSerr += yres * yres;
+
+	    for (k = 1; k <= n_predictors; k++) {
+		double yesti = 0.0;
+		double yresi;
+
+		/* linear model without predictor k */
+		for (i = 0; i <= n_predictors; i++) {
+		    if (i != k) {
+			j = k > i ? i : i - 1;
+			yesti += B[k][j] * mapx_val[i];
+		    }
+		}
+		yresi = mapy_val - yesti;
+
+		/* linear model without predictor k */
+		SSerr_without[k - 1] += yresi * yresi;
+
+		varX[k - 1] = (mapx_val[k] - meanX[k - 1]) * (mapx_val[k] - meanX[k - 1]);
+	    }
+	}
+
+	if (mapres_buf)
+	    Rast_put_d_row(mapres_fd, mapres_buf);
+	if (mapest_buf)
+	    Rast_put_d_row(mapest_fd, mapest_buf);
+    }
+    G_percent(rows, rows, 2);
+
+    fprintf(stdout, "n=%d\n", count);
+    /* coefficient of determination aka R squared */
+    Rsq = 1 - (SSerr / SStot);
+    fprintf(stdout, "Rsq=%f\n", Rsq);
+    /* adjusted coefficient of determination */
+    Rsqadj = 1 - ((SSerr * (count - 1)) / (SStot * (count - n_predictors - 1)));
+    fprintf(stdout, "Rsqadj=%f\n", Rsqadj);
+    /* F statistic */
+    /* F = ((SStot - SSerr) / (n_predictors)) / (SSerr / (count - n_predictors));
+     * , or: */
+    F = ((SStot - SSerr) * (count - n_predictors - 1)) / (SSerr * (n_predictors));
+    fprintf(stdout, "F=%f\n", F);
+
+    i = 0;
+    /* constant aka estimate for intercept in R */
+    fprintf(stdout, "b%d=%f\n", i, B[0][i]);
+    /* t score for R squared of the full model, unused */
+    t = sqrt(Rsq) * sqrt((count - 2) / (1 - Rsq));
+    /*
+    fprintf(stdout, "t%d=%f\n", i, t);
+    */
+
+    /* AIC, corrected AIC, and BIC information criteria for the full model */
+    AIC = count * log(SSerr / count) + 2 * (n_predictors + 1);
+    fprintf(stdout, "AIC=%f\n", AIC);
+    AICc = AIC + (2 * n_predictors * (n_predictors + 1)) / (count - n_predictors - 1);
+    fprintf(stdout, "AICc=%f\n", AICc);
+    BIC = count * log(SSerr / count) + log(count) * (n_predictors + 1);
+    fprintf(stdout, "BIC=%f\n", BIC);
+
+    /* error variance of the model, identical to R */
+    SE = SSerr / (count - n_predictors - 1);
+    /*
+    fprintf(stdout, "SE=%f\n", SE);
+    fprintf(stdout, "SSerr=%f\n", SSerr);
+    */
+
+    for (i = 0; i < n_predictors; i++) {
+
+	fprintf(stdout, "\nb%d=%f\n", i + 1, B[0][i + 1]);
+	if (n_predictors > 1) {
+	    double Rsqi, SEi, sumsqX_corr;
+
+	    /* corrected sum of squares for predictor [i] */
+	    sumsqX_corr = sumsqX[i] - sumX[i] * sumX[i] / (count - n_predictors - 1);
+
+	    /* standard error SE for predictor [i] */
+
+	    /* SE[i] with only one predictor: sqrt(SE / sumsqX_corr)
+	     * this does not work with more than one predictor */
+	    /* in R, SEi is sqrt(diag(R) * resvar) with
+	     * R = ???
+	     * resvar = rss / rdf = SE global
+	     * rss = sum of squares of the residuals
+	     * rdf = residual degrees of freedom = count - n_predictors - 1 */
+	    SEi = sqrt(SE / (Rsq * sumsqX_corr));
+	    /*
+	    fprintf(stdout, "SE%d=%f\n", i + 1, SEi);
+	    */
+
+	    /* Sum of squares for predictor [i] */
+	    /*
+	    fprintf(stdout, "SSerr%d=%f\n", i + 1, SSerr_without[i] - SSerr);
+	    */
+
+	    /* R squared of the model without predictor [i] */
+	    /* Rsqi = 1 - SSerr_without[i] / SStot; */
+	    /* the additional amount of variance explained
+	     * when including predictor [i] :
+	     * Rsq - Rsqi */
+	    Rsqi = (SSerr_without[i] - SSerr) / SStot;
+	    fprintf(stdout, "Rsq%d=%f\n", i + 1, Rsqi);
+
+	    /* t score for Student's t distribution, unused */
+	    t = (B[0][i + 1]) / SEi;
+	    /*
+	    fprintf(stdout, "t%d=%f\n", i + 1, t);
+	    */
+
+	    /* F score for Fisher's F distribution
+	     * here: F score to test if including predictor [i]
+	     * yields a significant improvement
+	     * after Lothar Sachs, Angewandte Statistik:
+	     * F = (Rsq - Rsqi) * (count - n_predictors - 1) / (1 - Rsq) */
+	    /* same like Sumsq / SE */
+	    /* same like (SSerr_without[i] / SSerr - 1) * (count - n_predictors - 1) */
+	    /* same like R-stats when entered in R-stats as last predictor */
+	    F = (SSerr_without[i] / SSerr - 1) * (count - n_predictors - 1);
+	    fprintf(stdout, "F%d=%f\n", i + 1, F);
+
+	    /* AIC, corrected AIC, and BIC information criteria for
+	     * the model without predictor [i] */
+	    AIC = count * log(SSerr_without[i] / count) + 2 * (n_predictors);
+	    fprintf(stdout, "AIC%d=%f\n", i + 1, AIC);
+	    AICc = AIC + (2 * (n_predictors - 1) * n_predictors) / (count - n_predictors - 2);
+	    fprintf(stdout, "AICc%d=%f\n", i + 1, AICc);
+	    BIC = count * log(SSerr_without[i] / count) + (n_predictors - 1) * log(count);
+	    fprintf(stdout, "BIC%d=%f\n", i + 1, BIC);
+	}
+    }
+    
+
+    for (i = 0; i < n_predictors; i++) {
+	Rast_close(mapx_fd[i]);
+	G_free(mapx_buf[i]);
+    }
+    Rast_close(mapy_fd);
+    G_free(mapy_buf);
+    
+    if (mapres_fd > -1) {
+	struct History history;
+
+	Rast_close(mapres_fd);
+	G_free(mapres_buf);
+
+	Rast_short_history(output_res->answer, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(output_res->answer, &history);
+    }
+
+    if (mapest_fd > -1) {
+	struct History history;
+
+	Rast_close(mapest_fd);
+	G_free(mapest_buf);
+
+	Rast_short_history(output_est->answer, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(output_est->answer, &history);
+    }
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.regression.multi/r.regression.multi.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.regression.multi/r.regression.multi.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.regression.multi/r.regression.multi.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,82 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.regression.multi</em> calculates a multiple linear regression from
+raster maps, according to the formula
+<div class="code"><pre>
+Y = b0 + sum(bi*Xi) + E
+</pre></div>
+where
+<div class="code"><pre>
+X = {X1, X2, ..., Xm}
+m = number of explaining variables
+Y = {y1, y2, ..., yn}
+Xi = {xi1, xi2, ..., xin}
+E = {e1, e2, ..., en}
+n = number of observations (cases)
+</pre></div>
+
+In R notation:
+<div class="code"><pre>
+Y ~ sum(bi*Xi)
+b0 is the intercept, X0 is set to 1
+</pre></div>
+
+<p>
+<em>r.regression.multi</em> is designed for large datasets that can not
+be processed in R. A p value is therefore not provided, because even
+very small, meaningless effects will become significant with a large
+number of cells. Instead it is recommended to judge by the estimator b,
+the amount of variance explained (R squared for a given variable) and
+the gain in AIC (AIC without a given variable minus AIC global must be
+positive) whether the inclusion of a given explaining variable in the
+model is justified.
+
+<h4>The global model</h4>
+The <em>b</em> coefficients (b0 is offset), R squared or coefficient of
+determination (Rsq) and F are identical to the ones obtained from
+R-stats's lm() function and R-stats's anova() function. The AIC value
+is identical to the one obtained from R-stats's stepAIC() function
+(in case of backwards stepping, identical to the Start value). The
+AIC value corrected for the number of explaining variables and the BIC
+(Bayesian Information Criterion) value follow the logic of AIC.
+
+<h4>The explaining variables</h4>
+R squared for each explaining variable represents the additional amount
+of explained variance when including this variable compared to when
+excluding this variable, that is, this amount of variance is explained
+by the current explaining variable after taking into consideration all
+the other explaining variables.
+<p>
+The F score for each explaining variable allows to test if the inclusion
+of this variable significantly increases the explaining power of the
+model, relative to the global model excluding this explaining variable.
+That means that the F value for a given explaining variable is only
+identical to the F value of the R-function <em>summary.aov</em> if the
+given explaining variable is the last variable in the R-formula. While
+R successively includes one variable after another in the order
+specified by the formula and at each step calculates the F value
+expressing the gain by including the current variable in addition to the
+previous variables, <em>r.regression.multi</em> calculates the F-value
+expressing the gain by including the current variable in addition to all
+other variables, not only the previous variables.
+<p>
+The AIC value is identical to the one obtained from the R-function
+stepAIC() when excluding this variable from the full model. The AIC
+value corrected for the number of explaining variables and the BIC value
+(Bayesian Information Criterion) value follow the logic of AIC. BIC is
+identical to the R-function stepAIC with k = log(n). AICc is not
+available through the R-function stepAIC.
+
+<h2>EXAMPLE</h2>
+
+North Carolina dataset:
+<div class="code"><pre>
+g.region rast=soils_Kfactor
+r.regression.multi mapx=elevation,aspect,slope mapy=soils_Kfactor
+</pre></div>
+
+<h2>AUTHOR</h2>
+
+Markus Metz
+
+<p><i>Last changed: $Date: 2011-11-16 07:54:16 +0100 (Wed, 16 Nov 2011) $</i>

Added: grass-addons/grass7/grass7/raster/r.regression.series/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.regression.series/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.regression.series/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.regression.series
+
+LIBES = $(STATSLIB) $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(STATSDEP) $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.regression.series/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.regression.series/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.regression.series/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,351 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.series
+ * 
+ * AUTHOR(S):    Markus Metz
+ *               based on r.series by
+ *               Glynn Clements <glynn gclements.plus.com> (original contributor)
+ *               Hamish Bowman <hamish_b yahoo.com>, Jachym Cepicky <jachym les-ejk.cz>,
+ *               Martin Wegmann <wegmann biozentrum.uni-wuerzburg.de>
+ * 
+ * PURPOSE:      regression between two time series
+ * 
+ * COPYRIGHT:    (C) 2011 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+/* TODO: use more stable two pass algorithm */
+
+#define SLOPE		0
+#define OFFSET		1
+#define CORCOEFF	2
+#define RSQUARE		3
+#define RSQUARE_ADJ	4
+#define F_VALUE		5
+#define T_VALUE		6
+
+struct reg_stats
+{
+    DCELL sumX, sumY, sumsqX, sumsqY, sumXY;
+    DCELL meanX, meanY;
+    DCELL A, B, R, R2;
+    int count;
+};
+
+static void reg(DCELL *result, struct reg_stats rs, int which)
+{
+    switch (which) {
+    case SLOPE:
+	*result = rs.B;
+	break;
+    case OFFSET:
+	*result = rs.meanY - rs.B * rs.meanX;
+	break;
+    case CORCOEFF:
+	*result = rs.R;
+	break;
+    case RSQUARE:
+	*result = rs.R2;
+	break;
+    case RSQUARE_ADJ:
+	*result = 1 - (1 - rs.R2) * ((rs.count - 1) / (rs.count - 2));
+	break;
+    case F_VALUE:
+	/* *result = rs.R2 / ((1 - rs.R2) / (rs.count - 2)); */
+	*result = rs.R2 * (rs.count - 2) / (1 - rs.R2);
+	break;
+    case T_VALUE:
+	*result = fabs(rs.R) * sqrt((rs.count - 2) / (1 - rs.R2));
+	break;
+    default:
+	Rast_set_d_null_value(result, 1);
+	break;
+    }
+
+    /* Check for NaN */
+    if (*result != *result)
+	Rast_set_d_null_value(result, 1);
+}
+
+struct menu
+{
+    int method;		        /* routine to compute new value */
+    char *name;			/* method name */
+    char *text;			/* menu display - full description */
+} menu[] = {
+    {SLOPE,         "slope",       "Linear regression slope"},
+    {OFFSET,        "offset",      "Linear regression offset"},
+    {CORCOEFF,      "corcoef",     "Correlation coefficient R"},
+    {RSQUARE,       "rsq",    	   "R squared (coefficient of determination)"},
+    {RSQUARE_ADJ,   "adjrsq",      "Adjusted R squared"},
+    {F_VALUE,       "f",           "F statistic"},
+    {T_VALUE,       "t",           "T statistic"},
+    {-1,         NULL,          NULL}
+};
+
+struct input
+{
+    const char *name;
+    int fd;
+    DCELL *buf;
+};
+
+struct output
+{
+    const char *name;
+    int fd;
+    DCELL *buf;
+    int method;
+};
+
+static char *build_method_list(void)
+{
+    char *buf = G_malloc(1024);
+    char *p = buf;
+    int i;
+
+    for (i = 0; menu[i].name; i++) {
+	char *q;
+
+	if (i)
+	    *p++ = ',';
+	for (q = menu[i].name; *q; p++, q++)
+	    *p = *q;
+    }
+    *p = '\0';
+
+    return buf;
+}
+
+static int find_method(const char *method_name)
+{
+    int i;
+
+    for (i = 0; menu[i].name; i++)
+	if (strcmp(menu[i].name, method_name) == 0)
+	    return i;
+
+    G_fatal_error(_("Unknown method <%s>"), method_name);
+
+    return -1;
+}
+
+int main(int argc, char *argv[])
+{
+    struct GModule *module;
+    struct
+    {
+	struct Option *xinput, *yinput, *output, *method;
+    } parm;
+    struct
+    {
+	struct Flag *nulls;
+    } flag;
+    int i;
+    int num_inputs;
+    struct input *xinputs, *yinputs;
+    int num_outputs;
+    struct output *outputs;
+    struct reg_stats rs;
+    struct History history;
+    int nrows, ncols;
+    int row, col;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("series"));
+    module->description =
+	_("Makes each output cell value a "
+	  "function of the values assigned to the corresponding cells "
+	  "in the input raster map layers.");
+
+    parm.xinput = G_define_standard_option(G_OPT_R_INPUTS);
+    parm.xinput->key = "xseries";
+
+    parm.yinput = G_define_standard_option(G_OPT_R_INPUTS);
+    parm.yinput->key = "yseries";
+
+    parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
+    parm.output->multiple = YES;
+
+    parm.method = G_define_option();
+    parm.method->key = "method";
+    parm.method->type = TYPE_STRING;
+    parm.method->required = YES;
+    parm.method->options = build_method_list();
+    parm.method->description = _("Regression parameters");
+    parm.method->multiple = YES;
+
+    flag.nulls = G_define_flag();
+    flag.nulls->key = 'n';
+    flag.nulls->description = _("Propagate NULLs");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    /* process the input maps */
+    for (i = 0; parm.xinput->answers[i]; i++)
+	;
+    num_inputs = i;
+
+    for (i = 0; parm.yinput->answers[i]; i++)
+	;
+    if (num_inputs != i)
+	G_fatal_error(_("The number of '%s' and '%s' maps must be identical"),
+		      parm.xinput->key, parm.yinput->key);
+
+    if (num_inputs < 3)
+	G_fatal_error(_("Regression parameters can not be calculated for less than 3 maps per series"));
+
+    if (num_inputs < 7)
+	G_warning(_("Regression parameters are dubious for less than 7 maps per series"));
+
+    xinputs = G_malloc(num_inputs * sizeof(struct input));
+    yinputs = G_malloc(num_inputs * sizeof(struct input));
+
+    for (i = 0; i < num_inputs; i++) {
+	struct input *px = &xinputs[i];
+	struct input *py = &yinputs[i];
+
+	px->name = parm.xinput->answers[i];
+	G_message(_("Reading raster map <%s>..."), px->name);
+	px->fd = Rast_open_old(px->name, "");
+	px->buf = Rast_allocate_d_buf();
+
+	py->name = parm.yinput->answers[i];
+	G_message(_("Reading raster map <%s>..."), py->name);
+	py->fd = Rast_open_old(py->name, "");
+	py->buf = Rast_allocate_d_buf();
+    }
+
+    /* process the output maps */
+    for (i = 0; parm.output->answers[i]; i++)
+	;
+    num_outputs = i;
+
+    for (i = 0; parm.method->answers[i]; i++)
+	;
+    if (num_outputs != i)
+	G_fatal_error(_("output= and method= must have the same number of values"));
+
+    outputs = G_calloc(num_outputs, sizeof(struct output));
+
+    for (i = 0; i < num_outputs; i++) {
+	struct output *out = &outputs[i];
+	const char *output_name = parm.output->answers[i];
+	const char *method_name = parm.method->answers[i];
+	int method = find_method(method_name);
+
+	out->name = output_name;
+	out->method = menu[method].method;
+	out->buf = Rast_allocate_d_buf();
+	out->fd = Rast_open_new(output_name, DCELL_TYPE);
+    }
+
+    /* initialise variables */
+
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+
+    /* process the data */
+    G_verbose_message(_("Percent complete..."));
+
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 2);
+
+	for (i = 0; i < num_inputs; i++) {
+	    Rast_get_d_row(xinputs[i].fd, xinputs[i].buf, row);
+	    Rast_get_d_row(yinputs[i].fd, yinputs[i].buf, row);
+	}
+
+	for (col = 0; col < ncols; col++) {
+	    int null = 0;
+
+	    rs.sumX = rs.sumY = rs.sumsqX = rs.sumsqY = rs.sumXY = 0.0;
+	    rs.meanX = rs.meanY = 0.0;
+	    rs.count = 0;
+
+	    for (i = 0; i < num_inputs; i++) {
+		DCELL x = xinputs[i].buf[col];
+		DCELL y = yinputs[i].buf[col];
+
+		if (Rast_is_d_null_value(&x) || Rast_is_d_null_value(&y))
+		    null = 1;
+		else {
+		    rs.sumX += x;
+		    rs.sumY += y;
+		    rs.sumsqX += x * x;
+		    rs.sumsqY += y * y;
+		    rs.sumXY += x * y;
+		    rs.count++;
+		}
+	    }
+	    if (rs.count > 1) {
+		DCELL tmp1 = rs.count * rs.sumXY - rs.sumX * rs.sumY;
+		DCELL tmp2 = rs.count * rs.sumsqX - rs.sumX * rs.sumX;
+
+		/* slope */
+		rs.B = tmp1 / tmp2;
+		/* correlation coefficient */
+		rs.R = tmp1 / sqrt((tmp2) * (rs.count * rs.sumsqY - rs.sumY * rs.sumY));
+		/* coefficient of determination aka R squared */
+		rs.R2 = rs.R * rs.R;
+
+		rs.meanX = rs.sumX / rs.count;
+
+		rs.meanY = rs.sumY / rs.count;
+	    }
+	    else {
+		rs.R = rs.R2 = rs.B = 0;
+	    }
+
+	    for (i = 0; i < num_outputs; i++) {
+		struct output *out = &outputs[i];
+
+		if (rs.count < 2 || (null && flag.nulls->answer))
+		    Rast_set_d_null_value(&out->buf[col], 1);
+		else {
+		    reg(&out->buf[col], rs, out->method);
+		}
+	    }
+	}
+
+	for (i = 0; i < num_outputs; i++)
+	    Rast_put_d_row(outputs[i].fd, outputs[i].buf);
+    }
+
+    G_percent(row, nrows, 2);
+
+    /* close maps */
+    for (i = 0; i < num_outputs; i++) {
+	struct output *out = &outputs[i];
+
+	Rast_close(out->fd);
+
+	Rast_short_history(out->name, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(out->name, &history);
+    }
+
+    for (i = 0; i < num_inputs; i++) {
+	Rast_close(xinputs[i].fd);
+	Rast_close(yinputs[i].fd);
+    }
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.regression.series/r.regression.series.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.regression.series/r.regression.series.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.regression.series/r.regression.series.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,113 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.regression.series</em> is a module to calculate linear
+regression parameters between two time series, e.g. NDVI and
+precipitation.
+<p>
+The module makes each output cell value a function of the values
+assigned to the corresponding cells in the two input raster map series.
+Following methods are available:
+
+<ul> 
+ <li>offset: Linear regression offset
+ <li>slope: Linear regression slope
+ <li>corcoef: Correlation Coefficent R
+ <li>rsq: Coefficient of determination = R squared
+ <li>adjrsq: Adjusted coefficient of determination
+ <li>f: F statistic
+ <li>t: T statistic
+ </ul> 
+
+<h2>DESCRIPTION</h2>
+
+The module assumes a simple linear regression of the form
+<div class="code"><pre>
+    y = a + b * x
+</pre></div>
+<p>
+<em>offset</em> is equivalent to <em>a</em> in the above equation, also 
+referred to as constant or intercept.
+<p>
+<em>slope</em> is equivalent to <em>b</em> in the above equation.
+<p>
+<em>corcoef</em> is the correlation coefficient R with a theoretical 
+range of -1,1.
+<p>
+<em>rsq</em> is the coefficient of determination, equivalent to 
+the squared correlation coefficient R<sup>2</sup>.
+<p>
+<em>adjrsq</em> is the coefficient of determination adjusted for the 
+number of samples, i.e. number of input maps per series.
+<p>
+<em>f</em> is the value of the F statistic.
+<p>
+<em>t</em> is the value of the T statistic.
+
+<h2>NOTES</h2>
+
+The number of maps in <em>xseries</em> and <em>yseries</em> must be 
+identical.
+<p>
+With <em>-n</em> flag, any cell for which any of the corresponding input cells are
+NULL is automatically set to NULL (NULL propagation). The aggregate function is not
+called, so all methods behave this way with respect to the <em>-n</em> flag.
+<p>
+Without <em>-n</em> flag, the complete list of inputs for each cell 
+(including NULLs) is passed to the function. Individual functions can
+handle data as they choose. Mostly, they just compute the parameter
+over the non-NULL values, producing a NULL result only if all inputs
+are NULL.
+<p>
+Linear regression (slope, offset, coefficient of determination) requires 
+an equal number of <em>xseries</em> and <em>yseries</em> maps.
+If the different time series have irregular time intervals, NULL raster 
+maps can be inserted into time series to make time intervals equal (see example).
+<p>
+The maximum number of raster maps to be processed is limited by the
+operating system. For example, both the hard and soft limits are
+typically 1024. The soft limit can be changed with e.g. <tt>ulimit -n
+1500</tt> (UNIX-based operating systems) but not higher than the hard
+limit. If it is too low, you can as superuser add an entry in
+
+<div class="code"><pre>
+/etc/security/limits.conf
+# <domain>      <type>  <item>         <value>
+your_username  hard    nofile          1500
+</pre></div>
+
+This would raise the hard limit to 1500 file. Be warned that more
+files open need more RAM.
+
+<h2>EXAMPLES</h2>
+
+Using <em>r.regression.series</em> with wildcards:
+<br>
+<div class="code"><pre>
+r.regression.series xseries="`g.mlist pattern='insitu_data.*' sep=,`" \
+	 yseries="`g.mlist pattern='invivo_data.*' sep=,`" \
+         output=insitu_data.rsquared method=rsq
+</pre></div>
+<p>
+Note the <em>g.mlist</em> module also supports regular expressions for
+selecting map names.
+
+<p>
+Example for multiple parameters to be computed in one run (3 resulting 
+parameters from 8 input maps, 4 maps per time series):
+<div class="code"><pre>
+r.regression.series x=xone,xtwo,xthree,xfour y=yone,ytwo,ythree,yfour \
+    out=res_offset,res_slope,res_adjrsq meth=offset,slope,adjrsq
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em><a href="r.series.html">r.series</a></em>,
+<em><a href="r.regression.line.html">r.regression.line</a></em>,
+<em><a href="g.mlist.html">g.mlist</a></em>,
+<em><a href="g.region.html">g.region</a></em>
+
+<h2>AUTHOR</h2>
+
+Markus Metz
+
+<p><i>Last changed: $Date: 2012-07-05 21:39:53 +0200 (Thu, 05 Jul 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.stream.basins/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,14 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.stream.basins
+
+LIBES = $(GISLIB) $(RASTERLIB) $(SEGMENTLIB) $(VECTORLIB) $(DBMILIB)
+DEPENDENCIES = $(GISDEP) $(RASTERDEP) $(SEGMENTDEP) $(VECTORDEP) $(DBMIDEP)
+
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
+

Added: grass-addons/grass7/grass7/raster/r.stream.basins/basins_fill.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/basins_fill.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/basins_fill.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,180 @@
+/* 
+   Link: a channel between junction
+   Ooutlet: is final cell of every segment
+   Segment: a channel which order remains unchanged in spite it pass through junction or not
+   Number of outlets shall be equal the number of segments
+   Number of junction shall be less than number of links
+ */
+
+/*
+   find outlets create table of outlets point, with r, c and value. depending of flag:
+   if flag -l is as anly last points of segment is added to table and uses the value is the category as value for whole basins
+   if flag -l = flase (default) last points of every link is added to table and uses the value is the category as value for subbasin
+   In both cases if flag -c is used it add out_num+1 value as value of point. That structure is next used in reset_catchments and fill_catchments fuctions
+ */
+
+/* fifo functions */
+/* insertion point: tail -> tail must always be unused */
+/* removal point: head + 1 */
+/* head == tail if last point removed or if only one free slot left */
+
+#include "local_proto.h"
+static int tail, head, fifo_count;
+
+int fifo_insert(POINT point)
+{
+    if (fifo_count == fifo_max)
+	G_fatal_error("fifo queue: circular buffer too small");
+
+    fifo_points[tail++] = point;
+    if (tail > fifo_max) {
+	G_debug(1, "tail > fifo_max");
+	tail = 0;
+    }
+    fifo_count++;
+    return 0;
+}
+
+POINT fifo_return_del(void)
+{
+    if (head >= fifo_max) {
+	G_debug(1, "head >= fifo_max");
+	head = -1;
+    }
+    fifo_count--;
+
+    return fifo_points[++head];
+}
+
+/*
+   this function adds points from outlet structure 
+   The lines below from function fill_catchments makes that 
+   outlet is not added do fifo
+   queue and basin is limited by next outlet
+
+   if (catchments[NR(i)][NR(i)]>0)
+   continue; 
+
+   It is simple trick but allow gives module its real funcionality
+
+   Buffer is an correction wchich allow to delinate basins even if vector point 
+   or coordinates do not lie exactly on stream. In that case a small one pixel buffer
+   is created. This is little risk functionality and must be used carefully.
+ */
+
+int ram_add_outlets(CELL **basins, int outlets_num)
+{
+    int i;
+
+    for (i = 0; i < outlets_num; ++i)
+	basins[outlets[i].r][outlets[i].c] = outlets[i].val;
+
+    return 0;
+}
+
+int seg_add_outlets(SEGMENT *basins, int outlets_num)
+{
+
+    int i;
+    int *basins_cell;
+
+    for (i = 0; i < outlets_num; ++i) {
+	basins_cell = &outlets[i].val;
+	segment_put(basins, basins_cell, outlets[i].r, outlets[i].c);
+    }
+    return 0;
+}
+
+/*
+   algorithm uses fifo queue for determining basins area. 
+ */
+
+int ram_fill_basins(OUTLET outlet, CELL **basins, CELL **dirs)
+{
+    int next_r, next_c;
+    int r, c, val, i, j;
+    POINT n_cell;
+
+    tail = 0;
+    head = -1;
+    fifo_count = 0;
+    r = outlet.r;
+    c = outlet.c;
+    val = outlet.val;
+
+    G_debug(1, "processing outlet at row %d col %d", r, c);
+
+    basins[r][c] = val;
+
+    while (tail != head) {
+	for (i = 1; i < 9; i++) {
+	    next_r = NR(i);
+	    next_c = NC(i);
+
+	    if (NOT_IN_REGION(i))
+		continue;
+	    j = DIAG(i);
+
+	    /* countributing cell, not yet assigned to a basin */
+	    if (dirs[next_r][next_c] == j && basins[next_r][next_c] == 0) {
+		basins[next_r][next_c] = val;
+		n_cell.r = next_r;
+		n_cell.c = next_c;
+		fifo_insert(n_cell);
+	    }
+	}			/* end for i... */
+
+	n_cell = fifo_return_del();
+	r = n_cell.r;
+	c = n_cell.c;
+    }				/* end while */
+    return 0;
+}
+
+int seg_fill_basins(OUTLET outlet, SEGMENT *basins, SEGMENT *dirs)
+{
+    int next_r, next_c;
+    int r, c, val, i, j;
+    POINT n_cell;
+    int dirs_cell, basins_cell;
+
+    tail = 0;
+    head = -1;
+    fifo_count = 0;
+    r = outlet.r;
+    c = outlet.c;
+    val = outlet.val;
+
+    G_debug(1, "processing outlet at row %d col %d", r, c);
+
+    segment_put(basins, &val, r, c);
+
+    while (tail != head) {
+	for (i = 1; i < 9; i++) {
+	    next_r = NR(i);
+	    next_c = NC(i);
+
+	    if (NOT_IN_REGION(i))
+		continue;
+	    j = DIAG(i);
+
+	    /* countributing cell, not yet assigned to a basin */
+	    segment_get(basins, &basins_cell, next_r, next_c);
+	    segment_get(dirs, &dirs_cell, next_r, next_c);
+
+	    if (dirs_cell == j && basins_cell == 0) {
+		segment_put(basins, &val, next_r, next_c);
+		n_cell.r = next_r;
+		n_cell.c = next_c;
+		fifo_insert(n_cell);
+	    }
+	}			/* end for i... */
+
+	n_cell = fifo_return_del();
+	r = n_cell.r;
+	c = n_cell.c;
+
+    }				/* end while */
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.basins/basins_inputs.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/basins_inputs.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/basins_inputs.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,274 @@
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+
+#include "local_proto.h"
+
+int process_coors(char **answers)
+{
+
+    int n, outlets_num;
+    double X, Y;
+    struct Cell_head window;
+
+    if (!answers)
+	G_fatal_error(_("At least one pair of coordinates must pe send"));
+
+    G_get_window(&window);
+
+    for (n = 0, outlets_num = 0; answers[n] != NULL; n += 2, outlets_num++) ;
+
+    outlets = (OUTLET *) G_malloc(outlets_num * sizeof(OUTLET));
+
+    for (n = 0, outlets_num = 0; answers[n] != NULL; n += 2, outlets_num++) {
+
+	if (!G_scan_easting(answers[n], &X, G_projection()))
+	    G_fatal_error("Wrong coordinate <%s>", answers[n]);
+
+	if (!answers[n + 1])
+	    G_fatal_error("Missing north coordinate for east %g", X);
+
+	if (!G_scan_northing(answers[n + 1], &Y, G_projection()))
+	    G_fatal_error("Wrong coordinate <%s>", answers[n + 1]);
+
+	if (X < window.west || X > window.east ||
+	    Y < window.south || Y > window.north)
+	    G_fatal_error("Coordinates outside window");
+
+	outlets[outlets_num].r = (window.north - Y) / window.ns_res;
+	outlets[outlets_num].c = (X - window.west) / window.ew_res;
+	outlets[outlets_num].val = outlets_num + 1;
+    }
+
+    return outlets_num;
+}
+
+int process_vector(char *in_point)
+{
+    char *mapset;
+    struct Cell_head window;
+    struct Map_info Map;
+    struct bound_box box;
+    int num_point = 0;
+    int type, i, cat;
+    struct line_pnts *sites;
+    struct line_cats *cats;
+
+    sites = Vect_new_line_struct();
+    cats = Vect_new_cats_struct();
+
+    mapset = G_find_vector2(in_point, "");
+    if (mapset == NULL)
+	G_fatal_error(_("Vector map <%s> not found"), in_point);
+
+    if (Vect_open_old(&Map, in_point, mapset) < 0)
+	G_fatal_error("Cannot open vector map <%s>", in_point);
+
+    G_get_window(&window);
+    Vect_region_box(&window, &box);
+
+    while ((type = Vect_read_next_line(&Map, sites, cats)) > -1) {
+	if (type != GV_POINT)
+	    continue;
+	if (Vect_point_in_box(sites->x[0], sites->y[0], sites->z[0], &box)) {
+	    num_point++;
+	}
+    }
+
+    outlets = (OUTLET *) G_malloc(num_point * sizeof(OUTLET));
+
+    Vect_rewind(&Map);
+    i = 0;
+    while ((type = Vect_read_next_line(&Map, sites, cats)) > -1) {
+	if (type != GV_POINT)
+	    continue;
+
+	if (!Vect_point_in_box(sites->x[0], sites->y[0], sites->z[0], &box))
+	    continue;
+
+	Vect_cat_get(cats, 1, &cat);
+
+	outlets[i].r = (int)Rast_northing_to_row(sites->y[0], &window);
+	outlets[i].c = (int)Rast_easting_to_col(sites->x[0], &window);
+	outlets[i].val = cat;
+	i++;
+    }
+
+    return num_point;
+}
+
+int ram_process_streams(char **cat_list, CELL **streams,
+			int number_of_streams, CELL **dirs, int lasts,
+			int cats)
+{
+    int i, cat;
+    int r, c, d;		/* d: direction */
+    int outlets_num = 0;
+    int next_stream = -1, cur_stream;
+    int out_max = ncols + nrows;
+
+    categories = NULL;
+
+    if (cat_list) {		/* only if there are at least one category */
+	categories = G_malloc((number_of_streams) * sizeof(int));
+	memset(categories, -1, (number_of_streams) * sizeof(int));
+
+	for (i = 0; cat_list[i] != NULL; ++i) {
+	    cat = atoi(cat_list[i]);
+	    if (cat < 1 || cat > number_of_streams)
+		G_fatal_error(_("Stream categories must be > 0 and < maximum stream category"));
+	    categories[cat] = cat;
+	}
+    }
+
+    G_message("Finding nodes...");
+    outlets = (OUTLET *) G_malloc((out_max) * sizeof(OUTLET));
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c)
+	    if (streams[r][c] > 0) {
+		if (outlets_num > 6 * (out_max - 1))
+		    G_fatal_error(_("Stream and direction maps probably do not match"));
+
+		if (outlets_num > (out_max - 1))
+		    outlets =
+			(OUTLET *) G_realloc(outlets,
+					     out_max * 6 * sizeof(OUTLET));
+
+		d = abs(dirs[r][c]);	/* r.watershed */
+
+		if (NOT_IN_REGION(d))
+		    next_stream = -1;	/* border */
+		else
+		    next_stream = (streams[NR(d)][NC(d)] > 0) ?
+			streams[NR(d)][NC(d)] : -1;
+
+		if (d == 0)
+		    next_stream = -1;
+
+		cur_stream = streams[r][c];
+
+		if (lasts) {
+		    if (next_stream < 0) {	/* is outlet! */
+
+			if (categories)
+			    if (categories[cur_stream] == -1)	/* but not in list */
+				continue;
+
+			outlets[outlets_num].r = r;
+			outlets[outlets_num].c = c;
+			outlets[outlets_num].val =
+			    (cats) ? outlets_num + 1 : streams[r][c];
+			outlets_num++;
+		    }
+		}
+		else {		/* not lasts */
+
+		    if (cur_stream != next_stream) {	/* is node or outlet! */
+
+			if (categories)
+			    if (categories[cur_stream] == -1)	/* but not in list */
+				continue;
+
+			outlets[outlets_num].r = r;
+			outlets[outlets_num].c = c;
+			outlets[outlets_num].val =
+			    (cats) ? outlets_num + 1 : streams[r][c];
+			outlets_num++;
+		    }
+		}		/* end if else lasts */
+	    }			/* end if streams */
+
+    return outlets_num;
+}
+
+int seg_process_streams(char **cat_list, SEGMENT *streams,
+			int number_of_streams, SEGMENT *dirs, int lasts,
+			int cats)
+{
+    int i, cat;
+    int r, c, d;		/* d: direction */
+    int outlets_num;
+    int next_stream = -1, cur_stream;
+    int streams_cell, dirs_cell, streams_next_cell;
+    int out_max = ncols + nrows;
+
+    categories = NULL;
+
+    if (cat_list) {
+	categories = G_malloc((number_of_streams) * sizeof(int));
+	memset(categories, -1, (number_of_streams) * sizeof(int));
+
+	for (i = 0; cat_list[i] != NULL; ++i) {
+	    cat = atoi(cat_list[i]);
+	    if (cat < 1 || cat > number_of_streams)
+		G_fatal_error(_("Stream categories must be > 0 and < maximum stream category"));
+	    categories[cat] = cat;
+	}
+    }
+    G_message("Finding nodes...");
+    outlets = (OUTLET *) G_malloc((out_max) * sizeof(OUTLET));
+    outlets_num = 0;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+
+	    segment_get(streams, &streams_cell, r, c);
+	    if (streams_cell > 0) {
+		if (outlets_num > 6 * (out_max - 1))
+		    G_fatal_error
+			("Stream and direction maps probably do not match");
+
+		if (outlets_num > (out_max - 1))
+		    outlets =
+			(OUTLET *) G_realloc(outlets,
+					     out_max * 6 * sizeof(OUTLET));
+
+		segment_get(dirs, &dirs_cell, r, c);
+		d = abs(dirs_cell);	/* abs */
+
+		if (NOT_IN_REGION(d))
+		    next_stream = -1;	/* border */
+		else {
+		    segment_get(streams, &streams_next_cell, NR(d), NC(d));
+		    next_stream =
+			(streams_next_cell > 0) ? streams_next_cell : -1;
+		}
+
+		if (d == 0)
+		    next_stream = -1;
+
+		cur_stream = streams_cell;
+
+		if (lasts) {
+
+		    if (next_stream < 0) {	/* is outlet! */
+			if (categories)
+			    if (categories[cur_stream] == -1)	/* but not in list */
+				continue;
+
+			outlets[outlets_num].r = r;
+			outlets[outlets_num].c = c;
+			outlets[outlets_num].val =
+			    (cats) ? outlets_num + 1 : cur_stream;
+			outlets_num++;
+		    }
+		}
+		else {		/* not lasts */
+
+		    if (cur_stream != next_stream) {	/* is outlet or node! */
+			if (categories)
+			    if (categories[cur_stream] == -1)	/* but not in list */
+				continue;
+
+			outlets[outlets_num].r = r;
+			outlets[outlets_num].c = c;
+			outlets[outlets_num].val =
+			    (cats) ? outlets_num + 1 : cur_stream;
+			outlets_num++;
+		    }
+		}		/* end if else lasts */
+	    }			/* end if streams */
+	}			/* end for */
+    return outlets_num;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.basins/io.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/io.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/io.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,564 @@
+#include "io.h"
+/* all in ram functions section */
+
+int ram_create_map(MAP * map, RASTER_MAP_TYPE data_type)
+{
+
+    /* 
+     * allocates 0 filled nrows*ncols map of type void;
+     * map parameters are stored in structure;
+     * map: map to be created;
+     * map type to be created must be CELL, FCELL, DCELL;
+     * */
+
+    int r;
+
+    if (data_type < 0 || data_type > 2)
+	G_fatal_error(_("ram_creat: Cannot create map of unrecognised type"));
+
+    map->data_type = data_type;
+    map->map_name = NULL;
+    map->nrows = Rast_window_rows();
+    map->ncols = Rast_window_cols();
+    map->data_size = Rast_cell_size(data_type);
+
+    /* preparing internal map */
+    switch (map->data_type) {
+    case CELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(CELL *));
+	break;
+
+    case FCELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(FCELL *));
+	break;
+
+    case DCELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(DCELL *));
+	break;
+    }
+
+    for (r = 0; r < map->nrows; ++r)
+	(map->map)[r] = G_calloc(map->ncols, map->data_size);
+
+    return 0;
+}
+
+int ram_read_map(MAP * map, char *input_map_name, int check_res,
+		 RASTER_MAP_TYPE check_data_type)
+{
+    /*
+     * Funciton read external map and put it in MAP structure (created with create_map)
+     * map: map to be read can be of any data type, read map is converted to target map if neccesary.
+     * input_map_name: name of the map to be read;
+     * map pointer to map stucture (created with create_map);
+     * check_res: [1]: check res correspondence between region and map [0 no check];
+     * check_data_type [CELL, FCELL, DCELL] check if reading map is of particular type, [-1] no check;
+     */
+
+    int r, c;
+    char *mapset;
+    struct Cell_head cellhd, this_window;
+    char *maptypes[] = { "CELL", "FCELL", "DCELL" };
+    int input_map_fd;
+    RASTER_MAP_TYPE input_data_type;
+    size_t input_data_size;
+    void *input_buffer = NULL;
+    void *input_pointer;
+
+    /* checking if map exist */
+    mapset = (char *)G_find_raster2(input_map_name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), input_map_name);
+
+    /* checking if region and input are the same */
+    G_get_window(&this_window);
+    Rast_get_cellhd(input_map_name, mapset, &cellhd);
+    if (check_res)
+	if (this_window.ew_res != cellhd.ew_res ||
+	    this_window.ns_res != cellhd.ns_res)
+	    G_fatal_error(_("Region resolution and map %s resolution differs. \
+		Run g.region rast=%s to set proper region resolution"),
+			  input_map_name, input_map_name);
+
+    /* checking if input map is of required type */
+    if (check_data_type != map->data_type)
+	G_debug(1,
+		"ram_open:required map type and internal map type differs: conversion forced!");
+    input_data_type = Rast_map_type(input_map_name, mapset);
+    if (check_data_type != -1)
+	if (input_data_type != check_data_type)
+	    G_fatal_error(_("<%s> is not of type %s"),
+			  input_map_name, maptypes[check_data_type]);
+
+    input_map_fd = Rast_open_old(input_map_name, mapset);
+    input_data_size = Rast_cell_size(input_data_type);
+
+    {				/* reading range */
+	struct Range map_range;
+	struct FPRange map_fp_range;
+	int min, max;
+
+	if (input_data_type == CELL_TYPE) {
+	    Rast_init_range(&map_range);
+	    Rast_read_range(input_map_name, mapset, &map_range);
+	    Rast_get_range_min_max(&map_range, &min, &max);
+	    map->min = (double)min;
+	    map->max = (double)max;
+	}
+	else {
+	    Rast_init_fp_range(&map_fp_range);
+	    Rast_read_fp_range(input_map_name, mapset, &map_fp_range);
+	    Rast_get_fp_range_min_max(&map_fp_range, &(map->min),
+				      &(map->max));
+	}
+    }
+    /* end opening and checking */
+
+    input_buffer = Rast_allocate_buf(input_data_type);
+
+    /* start reading */
+    G_message(_("Reading map <%s>"), input_map_name);
+
+    for (r = 0; r < map->nrows; ++r) {
+	G_percent(r, map->nrows, 2);
+
+	Rast_get_row(input_map_fd, input_buffer, r, input_data_type);
+	input_pointer = input_buffer;
+
+	for (c = 0; c < map->ncols; ++c)
+	    if (!Rast_is_null_value
+		(input_pointer + c * input_data_size, input_data_type))
+		switch (map->data_type) {
+		case CELL_TYPE:
+		    ((CELL **) map->map)[r][c] =
+			Rast_get_c_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case FCELL_TYPE:
+		    ((FCELL **) map->map)[r][c] =
+			Rast_get_f_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case DCELL_TYPE:
+		    ((DCELL **) map->map)[r][c] =
+			Rast_get_d_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		default:
+		    G_fatal_error(_("ram_open:Wrong internal data type"));
+		    break;
+		}
+    }				/*end for r */
+
+    G_free(input_buffer);
+    G_percent(r, map->nrows, 2);
+    Rast_close(input_map_fd);
+    return 0;
+}				/* end create floating point map */
+
+int ram_reset_map(MAP * map, int value)
+{
+    /*
+     * set all cells in the map to value
+     */
+    int r;
+
+    for (r = 0; r < map->nrows; ++r)
+	memset((map->map)[r], value, map->ncols * map->data_size);
+    return 0;
+}
+
+int ram_write_map(MAP * map, char *output_map_name,
+		  RASTER_MAP_TYPE output_data_type, int convert_to_null,
+		  double value)
+{
+    /* 
+     * write map to disk with output_map_name and output_data_type [CELL, FCELL, DCELL];
+     * if output_data_type = -1 than internal map type is used for output;
+     * if output map != -1 and types differ data_type, conversion is forced
+     * convert to null: check if convert to null a particular value in dataset;
+     */
+
+    int r, c;
+    int output_fd = 0;
+    struct History history;
+    void *row;
+
+    /* check for output format */
+    if (output_data_type == -1)
+	output_data_type = map->data_type;
+
+    if (output_data_type != map->data_type)
+	G_debug(1,
+		"ram_write:required map type and internal map type differs: conversion forced!");
+
+    G_message(_("Writing map <%s>"), output_map_name);
+    output_fd = Rast_open_new(output_map_name, output_data_type);
+
+    /* writing */
+    for (r = 0; r < map->nrows; ++r) {
+	G_percent(r, map->nrows, 2);
+
+	if (convert_to_null) {
+	    row = map->map[r];
+	    switch (map->data_type) {
+	    case CELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((CELL *) row)[c] == (CELL) value)
+			Rast_set_c_null_value(row + c * (map->data_size), 1);
+		break;
+	    case FCELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((FCELL *) row)[c] == (FCELL) value)
+			Rast_set_f_null_value(row + c * (map->data_size), 1);
+		break;
+	    case DCELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((DCELL *) row)[c] == (DCELL) value)
+			Rast_set_d_null_value(row + c * (map->data_size), 1);
+		break;
+	    default:
+		G_debug(1, "ram_null:Cannot convert to null at: %d %d", r, c);
+	    }
+	}
+
+	Rast_put_row(output_fd, (map->map)[r], output_data_type);
+    }
+    G_percent(r, map->nrows, 2);
+    Rast_close(output_fd);
+    Rast_short_history(output_map_name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(output_map_name, &history);
+    G_message(_("<%s> Done"), output_map_name);
+    return 0;
+}
+
+int ram_release_map(MAP *map)
+{
+    /* 
+     * free memory allocated for map, set pointer to null;
+     */
+    int r;
+
+    for (r = 0; r < map->nrows; ++r)
+	G_free((map->map)[r]);
+    G_free(map->map);
+    map = NULL;
+    return 0;
+}
+
+
+/* memory swap functions section */
+
+
+int seg_create_map(SEG * seg, int srows, int scols, int number_of_segs,
+		   RASTER_MAP_TYPE data_type)
+{
+    /* create segment  and returns pointer to it;
+     * seg must be declared first;
+     * parameters are stored in structure;
+     * seg: segment to be created;
+     * srows, scols segment size
+     * number of segs max number of segs stored in memory
+     * data_type to be created must be CELL, FCELL, DCELL;
+     */
+
+    char *filename;
+    int fd;
+    int local_number_of_segs;
+
+    seg->fd = -1;
+    seg->filename = NULL;
+    seg->map_name = NULL;
+    seg->mapset = NULL;
+    seg->data_type = data_type;
+    seg->nrows = Rast_window_rows();
+    seg->ncols = Rast_window_cols();
+
+    local_number_of_segs =
+	(seg->nrows / srows + 1) * (seg->ncols / scols + 1);
+    number_of_segs =
+	(number_of_segs >
+	 local_number_of_segs) ? local_number_of_segs : number_of_segs;
+
+    G_debug(3, "seg_creat:number of segments %d", number_of_segs);
+
+    switch (seg->data_type) {
+    case CELL_TYPE:
+	seg->data_size = sizeof(CELL);
+	break;
+    case FCELL_TYPE:
+	seg->data_size = sizeof(FCELL);
+	break;
+    case DCELL_TYPE:
+	seg->data_size = sizeof(DCELL);
+	break;
+    default:
+	G_fatal_error(_("seg_create: unrecognisabe data type"));
+    }
+
+    filename = G_tempfile();
+    fd = creat(filename, 0666);
+
+    if (0 >
+	segment_format(fd, seg->nrows, seg->ncols, srows, scols,
+		       seg->data_size)) {
+	close(fd);
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot format segment"));
+    }
+
+    close(fd);
+    if (0 > (fd = open(filename, 2))) {
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot re-open file"));
+    }
+
+    if (0 > (fd = segment_init(&(seg->seg), fd, number_of_segs))) {
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot init segment file or out of memory"));
+    }
+
+    seg->filename = G_store(filename);
+    seg->fd = fd;
+    return 0;
+}
+
+int seg_read_map(SEG * seg, char *input_map_name, int check_res,
+		 RASTER_MAP_TYPE check_data_type)
+{
+
+    /*
+     * Funciton read external map and put it in SEG structure (created with seg_create_map)
+     * map to be read can be of any data type, read map is converted if neccesary.
+     * input_map_name: name of the map to be read;
+     * seg: pointer to map stucture (created with create_map);
+     * check_res: [1]: check res correspondence between region and map [0 no check];
+     * check_data_type [CELL, FCELL, DCELL] check if reading map is of particular type, [-1] no check;
+     */
+
+    int input_fd;
+    int r, c;
+    char *mapset;
+    struct Cell_head cellhd, this_window;
+    char *maptypes[] = { "CELL", "FCELL", "DCELL" };
+    RASTER_MAP_TYPE input_data_type;
+    size_t input_data_size;
+    void *input_buffer = NULL;
+    void *target_buffer = NULL;
+    void *input_pointer = NULL;
+
+    /* checking if map exist */
+    mapset = (char *)G_find_raster2(input_map_name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("seg_read:Raster map <%s> not found"),
+		      input_map_name);
+    seg->mapset = mapset;
+
+    /* checking if region and input are the same */
+    G_get_window(&this_window);
+    Rast_get_cellhd(input_map_name, mapset, &cellhd);
+
+    /* check resolution equal anyinteger check;  equal 0 no check */
+    if (check_res)
+	if (this_window.ew_res != cellhd.ew_res ||
+	    this_window.ns_res != cellhd.ns_res)
+	    G_fatal_error(_("Region resolution and map %s resolution differs. \
+		Run g.region rast=%s to set proper region resolution"),
+			  input_map_name, input_map_name);
+
+    if (check_data_type != seg->data_type)
+	G_debug(1,
+		"ram_open:required map type and internal map type differs: conversion forced!");
+    input_data_type = Rast_map_type(input_map_name, mapset);
+    if (check_data_type != -1)
+	if (input_data_type != check_data_type)
+	    G_fatal_error(_("<%s> is not of type %s"),
+			  input_map_name, maptypes[check_data_type]);
+
+    input_fd = Rast_open_old(input_map_name, mapset);
+    input_data_size = Rast_cell_size(input_data_type);
+
+    {				/* reading range */
+	struct Range map_range;
+	struct FPRange map_fp_range;
+	int min, max;
+
+	if (input_data_type == CELL_TYPE) {
+	    Rast_init_range(&map_range);
+	    Rast_read_range(input_map_name, mapset, &map_range);
+	    Rast_get_range_min_max(&map_range, &min, &max);
+	    seg->min = (double)min;
+	    seg->max = (double)max;
+	}
+	else {
+	    Rast_init_fp_range(&map_fp_range);
+	    Rast_read_fp_range(input_map_name, mapset, &map_fp_range);
+	    Rast_get_fp_range_min_max(&map_fp_range, &(seg->min),
+				      &(seg->max));
+	}
+    }
+
+    /* end opening and checking */
+
+    G_message(_("Reading map <%s>"), input_map_name);
+    input_buffer = Rast_allocate_buf(input_data_type);
+
+    target_buffer = Rast_allocate_buf(seg->data_type);
+
+    for (r = 0; r < seg->nrows; ++r) {
+	G_percent(r, seg->nrows, 2);
+	Rast_get_row(input_fd, input_buffer, r, input_data_type);
+	input_pointer = input_buffer;
+	memset(target_buffer, 0, seg->ncols * seg->data_size);
+
+	for (c = 0; c < seg->ncols; ++c)
+	    if (!Rast_is_null_value
+		(input_pointer + c * input_data_size, input_data_type)) {
+		switch (seg->data_type) {
+		case CELL_TYPE:
+		    ((CELL *) target_buffer)[c] =
+			Rast_get_c_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case FCELL_TYPE:
+		    ((FCELL *) target_buffer)[c] =
+			Rast_get_f_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case DCELL_TYPE:
+		    ((DCELL *) target_buffer)[c] =
+			Rast_get_d_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		default:
+		    G_fatal_error(_("Wrong internal data type"));
+		    break;
+		}
+	    }
+
+	if (0 > segment_put_row(&(seg->seg), target_buffer, r)) {
+	    G_free(input_buffer);
+	    G_free(target_buffer);
+	    Rast_close(input_fd);
+	    G_fatal_error(_("seg_read: Cannot segment put row %d for map %s"),
+			  r, input_map_name);
+	}
+    }				/* end for row */
+
+    G_percent(r, seg->nrows, 2);
+    Rast_close(input_fd);
+    G_free(input_buffer);
+    G_free(target_buffer);
+
+    seg->map_name = G_store(input_map_name);
+    seg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int seg_reset_map(SEG * seg, int value)
+{
+    /*
+     * set all cells in the map to value
+     */
+    int r, c;
+
+    for (r = 0; r < seg->nrows; ++r)
+	for (c = 0; c < seg->ncols; ++c)
+	    segment_put(&(seg->seg), &value, r, c);
+
+    return 0;
+}
+
+int seg_write_map(SEG * seg, char *output_map_name,
+		  RASTER_MAP_TYPE output_data_type, int convert_to_null,
+		  double value)
+{
+    /* 
+     * write seg to disk with output_map_name and output_data_type [CELL, FCELL, DCELL];
+     * if output_data_type = -1 than internal map type is used for output;
+     * if output map != -1 and types differ data_type, conversion is forced
+     * convert to null: check if convert to null a particular value in dataset;
+     */
+    int output_fd;
+    int r, c;
+    void *output_buffer;
+    void *row;
+    struct History history;
+
+    /* check for output format */
+    if (output_data_type == -1)
+	output_data_type = seg->data_type;
+
+    if (output_data_type != seg->data_type)
+	G_debug(1,
+		"ram_write:required map type and internal map type differs: conversion forced!");
+
+    G_message(_("Writing map <%s>"), output_map_name);
+    output_fd = Rast_open_new(output_map_name, output_data_type);
+    output_buffer = Rast_allocate_buf(output_data_type);
+    segment_flush(&(seg->seg));
+
+    /* writing */
+    for (r = 0; r < seg->nrows; ++r) {
+
+	G_percent(r, seg->nrows, 2);
+	if (0 > segment_get_row(&(seg->seg), output_buffer, r))
+	    G_warning(_("seg_write: Cannot segment read row %d for map %s"),
+		      r, output_map_name);
+
+	if (convert_to_null) {
+
+	    row = output_buffer;
+	    switch (seg->data_type) {
+	    case CELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((CELL *) output_buffer)[c] == (CELL) value)
+			Rast_set_c_null_value(row + c * (seg->data_size), 1);
+		break;
+	    case FCELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((FCELL *) output_buffer)[c] == (FCELL) value)
+			Rast_set_f_null_value(row + c * (seg->data_size), 1);
+		break;
+	    case DCELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((DCELL *) output_buffer)[c] == (DCELL) value)
+			Rast_set_d_null_value(row + c * (seg->data_size), 1);
+		break;
+	    default:
+		G_warning(_("ram_null:Cannot convert to null at: %d %d"), r,
+			  c);
+	    }
+	}
+	Rast_put_row(output_fd, output_buffer, output_data_type);
+    }
+
+    G_percent(r, seg->nrows, 2);
+    G_free(output_buffer);
+    Rast_close(output_fd);
+    Rast_short_history(output_map_name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(output_map_name, &history);
+    G_message(_("%s Done"), output_map_name);
+
+    return 0;
+}
+
+int seg_release_map(SEG * seg)
+{
+    /* 
+     * release segment close files, set pointers to null;
+     */
+    segment_release(&(seg->seg));
+    close(seg->fd);
+    unlink(seg->filename);
+
+    if (seg->map_name)
+	G_free(seg->map_name);
+    if (seg->mapset)
+	G_free(seg->mapset);
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.basins/io.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/io.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/io.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/segment.h>
+
+#define NOT_IN_REGION(x) (r + nextr[(x)] < 0 || r + nextr[(x)] > (nrows - 1) || \
+                          c + nextc[(x)] < 0 || c + nextc[(x)] > (ncols - 1))
+#define NR(x) (r + nextr[(x)])
+#define NC(x) (c + nextc[(x)])
+#define INDEX(r,c) ((r) * ncols + (c))
+#define DIAG(x) (((x) + 4) > 8 ? ((x) - 4) : ((x) + 4))
+
+#define SROWS 256
+#define SCOLS 256
+
+typedef struct {
+	void **map; /* matrix of data */
+	double min, max; /* data range : may requre casting */
+	int nrows, ncols;
+	char *map_name; /* map name, unused */
+	RASTER_MAP_TYPE data_type; /* type of data */
+	size_t data_size; /* type of data */
+} MAP;
+
+typedef struct {
+	SEGMENT seg;		/* segmented data store */
+	int fd;					/* segment temporary file name descriptor */
+	char *filename; /* segment temporary file name */
+	char *map_name; /* map name converted to segment */
+	char *mapset;
+	int nrows, ncols; /* store nrows and rcols */
+	RASTER_MAP_TYPE data_type; /* data type of the map */
+	size_t data_size; /* size of cell returned by sizeof */
+	double min, max; /* data range */
+} SEG;
+
+
+/* all in ram functions */
+int ram_create_map(MAP *, RASTER_MAP_TYPE);
+int ram_read_map(MAP *, char *, int, RASTER_MAP_TYPE);
+int ram_reset_map(MAP *, int);
+int ram_write_map(MAP *, char *, RASTER_MAP_TYPE, int, double);
+int ram_release_map(MAP *);
+int ram_destory_map(MAP *);
+
+/* memory swap functions */
+int seg_create_map(SEG *, int, int, int, RASTER_MAP_TYPE);
+int seg_read_map(SEG *, char *, int, RASTER_MAP_TYPE);
+int seg_reset_map (SEG *, int);
+int seg_write_map(SEG *, char *, RASTER_MAP_TYPE, int, double);
+int seg_release_map(SEG *);
+

Added: grass-addons/grass7/grass7/raster/r.stream.basins/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,17 @@
+#include "io.h"
+#include "local_vars.h"
+
+int process_coors(char **answers);
+int process_vector(char *in_point);
+
+int ram_fill_basins(OUTLET outlet, CELL **basins, CELL **dirs);
+int ram_add_outlets(CELL **basins, int outlets_num);
+int ram_process_streams(char **cat_list, CELL **streams,
+			int number_of_streams, CELL **dirs, int lasts,
+			int cats);
+
+int seg_fill_basins(OUTLET outlet, SEGMENT *basins, SEGMENT *dirs);
+int seg_add_outlets(SEGMENT *basins, int outlets_num);
+int seg_process_streams(char **cat_list, SEGMENT *streams,
+			int number_of_streams, SEGMENT *dirs, int lasts,
+			int cats);

Added: grass-addons/grass7/grass7/raster/r.stream.basins/local_vars.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/local_vars.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/local_vars.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/vector.h>
+#include <grass/dbmi.h>
+
+#ifdef MAIN
+#  define GLOBAL
+#else
+#  define GLOBAL extern
+#endif
+
+typedef struct {
+	int r,c;
+	int val;
+} OUTLET;
+
+typedef struct {
+	int r,c;
+	} POINT;
+
+GLOBAL int nextr[9];
+GLOBAL int nextc[9];
+
+GLOBAL OUTLET* outlets;
+GLOBAL OUTLET* border_outlets;
+GLOBAL int* categories;
+GLOBAL int nrows, ncols;
+GLOBAL int fifo_max;
+GLOBAL POINT* fifo_points;
+
+
+
+
+
+

Added: grass-addons/grass7/grass7/raster/r.stream.basins/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,253 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.stream.basins
+ * AUTHOR(S):    Jarek Jasiewicz jarekj amu.edu.pl
+ *               
+ * PURPOSE:      Calculate basins according user' input data.
+ *               It uses multiple type of inputs:
+ * 							 r.stream.order, r.stream.extract or r.watershed stream  map 
+ *               list of categoires to create basins (require stream map);
+ *               vector file containing outputs;
+ *               list of coordinates;
+ *               with analogous  direction map;
+ *
+ * COPYRIGHT:    (C) 2002,2010 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *   	    	 	  License (>=v2). Read the file COPYING that comes with GRASS
+ *   	    	 	  for details.
+ *
+ *****************************************************************************/
+#define MAIN
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int nextr[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+int nextc[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+
+int main(int argc, char *argv[])
+{
+
+    struct GModule *module;
+    struct Option *in_dir_opt,
+	*in_coor_opt,
+	*in_stm_opt,
+	*in_stm_cat_opt, *in_point_opt, *opt_basins, *opt_swapsize;
+
+    struct Flag *flag_zerofill, *flag_cats, *flag_lasts, *flag_segmentation;
+
+    int b_test = 0;		/* test which option have been choosed: like chmod */
+    int segmentation, zerofill, lasts, cats;
+    int i, outlets_num = 0;
+    int max_number_of_streams;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->description = _("Delineate basins according user' input. \
+	Input can be stream network, point file with outlets or outlet coordinates");
+    G_add_keyword("basins creation");
+
+    in_dir_opt = G_define_standard_option(G_OPT_R_INPUT);	/* input directon file */
+    in_dir_opt->key = "dirs";
+    in_dir_opt->description = _("Name of flow direction input map");
+
+    in_coor_opt = G_define_option();	/* input coordinates de outlet */
+    in_coor_opt->key = "coors";
+    in_coor_opt->type = TYPE_STRING;
+    in_coor_opt->key_desc = "x,y";
+    in_coor_opt->answers = NULL;
+    in_coor_opt->required = NO;
+    in_coor_opt->multiple = YES;
+    in_coor_opt->description = _("Basin's outlet's coordinates: E,N");
+
+    in_stm_opt = G_define_standard_option(G_OPT_R_INPUT);	/* input stream file file */
+    in_stm_opt->key = "streams";
+    in_stm_opt->required = NO;
+    in_stm_opt->description = _("Name of stream mask input map");
+
+    in_stm_cat_opt = G_define_option();	/* input stream category - optional */
+    in_stm_cat_opt->key = "cats";
+    in_stm_cat_opt->type = TYPE_STRING;
+    in_stm_cat_opt->required = NO;
+    in_stm_cat_opt->description =
+	_("Create basins only for these categories:");
+
+    in_point_opt = G_define_standard_option(G_OPT_V_INPUT);	/* input point outputs - optional */
+    in_point_opt->key = "points";
+    in_point_opt->required = NO;
+    in_point_opt->description = _("Name of vector points map");
+
+    opt_swapsize = G_define_option();
+    opt_swapsize->key = "memory";
+    opt_swapsize->type = TYPE_INTEGER;
+    opt_swapsize->answer = "300";
+    opt_swapsize->description = _("Max memory used in memory swap mode (MB)");
+    opt_swapsize->guisection = _("Optional");
+
+    opt_basins = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_basins->key = "basins";
+    opt_basins->description = _("Output basin map");
+
+    /*flags */
+    flag_zerofill = G_define_flag();
+    flag_zerofill->key = 'z';
+    flag_zerofill->description =
+	_("Create zero-value background instead of NULL");
+
+    flag_cats = G_define_flag();
+    flag_cats->key = 'c';
+    flag_cats->description =
+	_("Use unique category sequence instead of input streams");
+
+    flag_lasts = G_define_flag();
+    flag_lasts->key = 'l';
+    flag_lasts->description = _("Create basins only for last stream links");
+
+    flag_segmentation = G_define_flag();
+    flag_segmentation->key = 'm';
+    flag_segmentation->description = _("Use memory swap (operation is slow)");
+
+    if (G_parser(argc, argv))	/* parser */
+	exit(EXIT_FAILURE);
+
+    zerofill = (flag_zerofill->answer == 0);
+    cats = (flag_cats->answer != 0);
+    lasts = (flag_lasts->answer != 0);
+    segmentation = (flag_segmentation->answer != 0);
+
+    if (!in_coor_opt->answers && !in_stm_opt->answer && !in_point_opt->answer)
+	G_fatal_error(_("One basin's outlet definition is required"));
+
+    if (in_stm_cat_opt->answers && !in_stm_opt->answer)
+	G_fatal_error(_("If cats stream file is required"));
+
+    if (in_coor_opt->answers)
+	b_test += 1;
+    if (in_stm_opt->answer)
+	b_test += 2;
+    if (in_point_opt->answer)
+	b_test += 4;
+
+    if (b_test != 1 && b_test != 2 && b_test != 4)
+	G_fatal_error("Only one outlet definition is allowed");
+
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+
+    if (G_legal_filename(opt_basins->answer) < 0)
+	G_fatal_error(_("<%s> is an illegal basin name"), opt_basins->answer);
+
+
+    /* ALL IN RAM VERSION */
+    if (!segmentation) {
+	MAP map_dirs, map_streams, map_basins;
+	CELL **streams = NULL, **dirs, **basins;
+
+	G_message("ALL IN RAM CALCULATION");
+
+	ram_create_map(&map_dirs, CELL_TYPE);
+	ram_read_map(&map_dirs, in_dir_opt->answer, 1, CELL_TYPE);
+	dirs = (CELL **) map_dirs.map;
+
+
+	switch (b_test) {
+	case 1:
+	    G_message("Calculate basins using coordinates...");
+	    outlets_num = process_coors(in_coor_opt->answers);
+	    break;
+
+	case 2:
+	    G_message("Calculate basins using streams...");
+	    ram_create_map(&map_streams, CELL_TYPE);
+	    ram_read_map(&map_streams, in_stm_opt->answer, 1, CELL_TYPE);
+	    streams = (CELL **) map_streams.map;
+	    max_number_of_streams = (int)map_streams.max + 1;
+	    outlets_num = ram_process_streams(in_stm_cat_opt->answers,
+					      streams, max_number_of_streams,
+					      dirs, lasts, cats);
+	    ram_release_map(&map_streams);
+	    break;
+
+	case 4:
+	    G_message("Calculate basins using point file...");
+	    outlets_num = process_vector(in_point_opt->answer);
+	    break;
+	}
+
+	ram_create_map(&map_basins, CELL_TYPE);
+	basins = (CELL **) map_basins.map;
+	ram_add_outlets(basins, outlets_num);
+	fifo_max = 4 * (nrows + ncols);
+	fifo_points = (POINT *) G_malloc((fifo_max + 1) * sizeof(POINT));
+
+	for (i = 0; i < outlets_num; ++i)
+	    ram_fill_basins(outlets[i], basins, dirs);
+
+	G_free(fifo_points);
+	ram_write_map(&map_basins, opt_basins->answer, CELL_TYPE, zerofill,
+		      0);
+	ram_release_map(&map_dirs);
+	ram_release_map(&map_basins);
+
+    }				/* end ram */
+
+    /* SEGMENT VERSION */
+
+    if (segmentation) {
+	SEG map_dirs, map_streams, map_basins;
+	SEGMENT *streams = NULL, *dirs, *basins;
+	int number_of_segs;
+
+	G_message("MEMORY SWAP CALCULATION: MAY TAKE SOME TIME!");
+
+	number_of_segs = (int)atof(opt_swapsize->answer);
+	number_of_segs = number_of_segs < 32 ? (int)(32 / 0.12) : number_of_segs / 0.12;
+
+	seg_create_map(&map_dirs, SROWS, SCOLS, number_of_segs, CELL_TYPE);
+	seg_read_map(&map_dirs, in_dir_opt->answer, 1, CELL_TYPE);
+	dirs = &map_dirs.seg;
+
+	switch (b_test) {
+	case 1:
+	    G_message("Calculate basins using coordinates...");
+	    outlets_num = process_coors(in_coor_opt->answers);
+	    break;
+
+	case 2:
+	    G_message("Calculate basins using streams...");
+	    seg_create_map(&map_streams, SROWS, SCOLS, number_of_segs,
+			   CELL_TYPE);
+	    seg_read_map(&map_streams, in_stm_opt->answer, 1, CELL_TYPE);
+	    streams = &map_streams.seg;
+	    max_number_of_streams = (int)map_streams.max + 1;
+	    outlets_num = seg_process_streams(in_stm_cat_opt->answers,
+					      streams, max_number_of_streams,
+					      dirs, lasts, cats);
+	    seg_release_map(&map_streams);
+	    break;
+
+	case 4:
+	    G_message("Calculate basins using point file...");
+	    outlets_num = process_vector(in_point_opt->answer);
+	    break;
+	}
+
+	seg_create_map(&map_basins, SROWS, SCOLS, number_of_segs, CELL_TYPE);
+	basins = &map_basins.seg;
+	seg_add_outlets(basins, outlets_num);
+	fifo_max = 4 * (nrows + ncols);
+	fifo_points = (POINT *) G_malloc((fifo_max + 1) * sizeof(POINT));
+
+	for (i = 0; i < outlets_num; ++i)
+	    seg_fill_basins(outlets[i], basins, dirs);
+	G_free(fifo_points);
+	seg_write_map(&map_basins, opt_basins->answer, CELL_TYPE, zerofill,
+		      0);
+	seg_release_map(&map_dirs);
+	seg_release_map(&map_basins);
+    }
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.stream.basins/r.stream.basins.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.basins/r.stream.basins.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.basins/r.stream.basins.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,191 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>-z</b></dt>
+<dd>Creates zero-value background instead of NULL. For some reason (like map
+algebra calculation) zero-valued background may be required. This flag produces
+zero-filled background instead of null (default).</dd>
+<dt><b>-c</b></dt>
+<dd>By default r.stream.basins uses streams category as basin category. In some
+cases - for example if stream map is product of map algebra and separete streams
+may not have unique values this option will create new category sequence for
+each basin (do not work in vector point mode)
+</dd>
+<dt><b>-l</b></dt>
+<dd>By default r.stream.basins create basins for all unique streams. This option
+delinate basins only for last streams ignoring upstreams (do not work in vector
+point mode).
+</dd>
+
+<dt><b>dirs</b></dt>
+<dd>Flow direction: name of input direction map produced by r.watershed or
+r.stream.extract. If r.stream.extract output map is used, it only has non-NULL
+values in places where streams occur. NULL (nodata) cells are ignored, zero and
+negative values are valid direction data if they vary from -8 to 8 (CCW from
+East in steps of 45 degrees). Direction map shall be of type CELL values. Region
+resolution and map resoultion must be the same. 
+Also <em>stream</em> network map (if used) and direction map must have the same
+resolution. It is checked by default. If resolutions differ the module informs
+about it and stops. Region boundary and maps boundary may be differ but it may
+lead to unexpected results.</dd>
+
+<dt><b>coors</b></dt>
+<dd>East and north coordinates for basin outlet. It can delinate only one basin
+using that option. This option simply copies funcionality of <a
+href="r.water.outlet.html">r.water.outlet</a>.
+</dd>
+<dt><b>streams</b></dt>
+<dd>Stream network: name of input stream map on which ordering will be performed
+produced by r.watershed or r.stream.extract. Because streams network produced by
+r.watershed and r.stream.extract may slighty differ in detail it is required to
+use both stream and direction map produced by the same module. Stream background
+shall have NULL value or zero value. Background values of NULL are by default
+produced by r.watershed and r.stream.extract. If not 0 or NULL use <a
+href="r.mapcalc.html">r.mapcalc</a> to set background values to null.  
+</dd>
+
+<dt><b>cats</b></dt>
+<dd>Stream categories to delineate basins for: All categories which are not in
+stream map are ignored. It can be used with stream network created by
+r.watershed, r.stream.extract or r.stream.order. For r.stream.order use category
+of order for which basins must be created. For example to delineate only basins
+for order two use cats=2. If you need unique category for every basin use -c
+flag.
+</dd>
+
+<dt><b>points</b></dt>
+<dd>Vector file containing basins outlet as vector points. Only point's
+categories are used to prepare basins. Table attached to it is ignored. Every
+point shall have his own unique category. In that mode flags -l and -c are
+ignored
+</dd>
+</dl>
+
+
+<h2>OUTPUTS</h2>
+<p>The module produces one raster map with basins acording user's rules</p>
+
+
+<h2>DESCRIPTION</h2>
+
+Module r.stream.basins is prepared to delineate basins and subasins with
+different input data. Module is prepared to delineate unrestricted number of
+basins in one step. It can delineate basins with three methods:
+<ul>
+<li>Using coordinates: his option simply copies funcionality of <a
+href="r.water.outlet.html">r.water.outlet</a>.
+<li>Using vector points: it allow to mannually point outlets with any method
+<li>Using streams (most advanced) it allow on lots of modifications. See
+examples for more details.
+</ul>
+Only one method can be used at once. Methods cannot be mixed.
+<p>
+The most recommended method require two maps: direction and streams. In spite of
+in stream map we can store information required to proper delineation, we can
+also enumarate stream categories for which basins are to be created (cats
+option). Module is prepared to work with output data of <em>r.watershed,
+r.stream.extract, r.stream.order</em> also with modification done by
+<em>r.recalss</em> and <em>r.mapcalc</em>. r.stream.basin can delineate basins
+according outlets marked by raster streams, and polygons, vector points and
+numerical coordinates. If outlets are marked by points or coordinates it
+delineate basins which cells contribute to that points, if outlets are marked by
+streams it delineate cells which contribute to the last (downstream) cell of the
+every stream. If outlets are marked by polygon it delineate cells contributing
+to most downstream cell of the polygon. If polygon covers more outlets than of
+one basins it will create collective basin for all outlets  with common
+category.
+
+
+<h2>NOTES</h2>
+<p>
+To receive good results outlets markers created by user shall overlapping with
+streams. On the other way basins could results with very small area. Input maps
+must be in CELL format (default output of r.watershed, r.stream.order  and
+r.stream.extract)<p>
+Module can work only if direction map, stream map and region map has same
+settings. It is also required that stream map and direction map come from the
+same source. For lots of reason this limitation probably cannot be omitted.  
+this means if stream map comes from r.stream.extract also direction map from
+r.stream.extract must be used. If stream network was generated with MFD method
+also MFD direction map must be used. Nowadays f direction map comes from
+r.stream.extract  must be patched by direction map from r.watershed. (with
+r.patch). 
+
+<h2>EXAMPLES</h2>
+<p>
+To delineate all basins with categories of streams:
+<p>
+<code>r.stream.basins dir=dirs stream=streams basins=bas_basins_elem</code>
+<p>
+To determine major and minor basins in area, definied by outlets, ignoring
+subbasins use  - l flag. That flag ignores all nodes and uses only real outlets
+(in most cases that on map border):
+<p>
+<code>r.stream.basins -l dir=dirs stream=streams basins=bas_basins_last</code>
+
+<p>
+<code>r.stream.basins dir=dirs coors=639936.623832,216939.836449</code>
+
+<p>
+To delineate one or more particular basins defined by given streams, add simply
+stream categories:
+<div class="code"><pre>
+r.stream.basins -lc dirs=dirs streams=streams cats=2,7,184 basins=bas_basin
+</pre></div>
+
+<p>
+Do delineate basins of particular order we must use the following procedure: 
+
+<div class="code"><pre>
+r.stream.basins -lc dirs=dirs streams=strahler cats=2
+basins=bas_basin_strahler_2
+</pre></div>
+
+<p>
+The usage of polygons as outlets markers is very useful when exact stream course
+cannot be cleary determined before running analysis, but the area of its
+occurrence can be determined (mostly in iterative simulations) Example uses
+r.circle but can be substituted by any polygon created for example  with
+v.digit:
+<div class="code"><pre>
+r.circle -b output=circle coordinate=639936.623832,216939.836449 max=200
+r.stream.basins -c dirs=dirs streams=circle basins=bas_simul
+</pre></div>
+<p>
+To determine areas of contribution to streams of particular order  use as
+streams the result of ordering:
+<p>
+<div class="code"><pre>
+r.stream.basins dirs=dirs streams=ord_strahler basins=bas_basin_strahler
+</pre></div>
+<p>
+Determination of areas of potential source of pollution. The example will be
+done for lake marked with FULL_HYDR 8056 in North Carolina sample dataset. The
+lake shall be extracted and converted to binary raster map.
+
+<div class="code"><pre>
+v.extract -d input=lakes at PERMANENT output=lake8056 type=area layer=1
+'where=FULL_HYDRO = 8056' new=-1 
+v.to.rast input=lake8056 output=lake8056 use=val type=area layer=1 value=1
+r.stream.basins dirs=dirs streams=lake8056 basins=bas_basin_lake
+</pre></div>
+<p>
+See also tutorial: <a href="http://grass.OSGeo.org/wiki/R.stream.*">http://grass.OSGeo.org/wiki/R.stream.*</a>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.watershed.html">r.watershed</a>,
+<a href="r.stream.extract.html">r.stream.extract</a>,
+<a href="r.stream.order.html">r.stream.order</a>,
+<a href="r.stream.stats.html">r.stream.stats</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+<a href="r.reclass.html">r.reclass</a>,
+<a href="r.patch.html">r.patch</a>
+</em>
+
+<h2>AUTHOR</h2>
+Jarek Jasiewicz, Adam Mickiewicz University, Geoecology and Geoinformation
+Institute.
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>
+

Added: grass-addons/grass7/grass7/raster/r.stream.channel/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.stream.channel
+
+LIBES = $(GISLIB) $(RASTERLIB) $(SEGMENTLIB)
+DEPENDENCIES = $(GISDEP) $(RASTERDEP) $(SEGMENTDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
+

Added: grass-addons/grass7/grass7/raster/r.stream.channel/io.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/io.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/io.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,564 @@
+#include "io.h"
+/* all in ram functions section */
+
+int ram_create_map(MAP * map, RASTER_MAP_TYPE data_type)
+{
+
+    /* 
+     * allocates 0 filled nrows*ncols map of type void;
+     * map parameters are stored in structure;
+     * map: map to be created;
+     * map type to be created must be CELL, FCELL, DCELL;
+     * */
+
+    int r;
+
+    if (data_type < 0 || data_type > 2)
+	G_fatal_error(_("ram_creat: Cannot create map of unrecognised type"));
+
+    map->data_type = data_type;
+    map->map_name = NULL;
+    map->nrows = Rast_window_rows();
+    map->ncols = Rast_window_cols();
+    map->data_size = Rast_cell_size(data_type);
+
+    /* preparing internal map */
+    switch (map->data_type) {
+    case CELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(CELL *));
+	break;
+
+    case FCELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(FCELL *));
+	break;
+
+    case DCELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(DCELL *));
+	break;
+    }
+
+    for (r = 0; r < map->nrows; ++r)
+	(map->map)[r] = G_calloc(map->ncols, map->data_size);
+
+    return 0;
+}
+
+int ram_read_map(MAP * map, char *input_map_name, int check_res,
+		 RASTER_MAP_TYPE check_data_type)
+{
+    /*
+     * Funciton read external map and put it in MAP structure (created with create_map)
+     * map: map to be read can be of any data type, read map is converted to target map if neccesary.
+     * input_map_name: name of the map to be read;
+     * map pointer to map stucture (created with create_map);
+     * check_res: [1]: check res correspondence between region and map [0 no check];
+     * check_data_type [CELL, FCELL, DCELL] check if reading map is of particular type, [-1] no check;
+     */
+
+    int r, c;
+    char *mapset;
+    struct Cell_head cellhd, this_window;
+    char *maptypes[] = { "CELL", "FCELL", "DCELL" };
+    int input_map_fd;
+    RASTER_MAP_TYPE input_data_type;
+    size_t input_data_size;
+    void *input_buffer = NULL;
+    void *input_pointer;
+
+    /* checking if map exist */
+    mapset = (char *)G_find_raster2(input_map_name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), input_map_name);
+
+    /* checking if region and input are the same */
+    G_get_window(&this_window);
+    Rast_get_cellhd(input_map_name, mapset, &cellhd);
+    if (check_res)
+	if (this_window.ew_res != cellhd.ew_res ||
+	    this_window.ns_res != cellhd.ns_res)
+	    G_fatal_error(_("Region resolution and map %s resolution differs. \
+		Run g.region rast=%s to set proper region resolution"),
+			  input_map_name, input_map_name);
+
+    /* checking if input map is of required type */
+    if (check_data_type != map->data_type)
+	G_debug(1,
+		"ram_open:required map type and internal map type differs: conversion forced!");
+    input_data_type = Rast_map_type(input_map_name, mapset);
+    if (check_data_type != -1)
+	if (input_data_type != check_data_type)
+	    G_fatal_error(_("<%s> is not of type %s"),
+			  input_map_name, maptypes[check_data_type]);
+
+    input_map_fd = Rast_open_old(input_map_name, mapset);
+    input_data_size = Rast_cell_size(input_data_type);
+
+    {				/* reading range */
+	struct Range map_range;
+	struct FPRange map_fp_range;
+	int min, max;
+
+	if (input_data_type == CELL_TYPE) {
+	    Rast_init_range(&map_range);
+	    Rast_read_range(input_map_name, mapset, &map_range);
+	    Rast_get_range_min_max(&map_range, &min, &max);
+	    map->min = (double)min;
+	    map->max = (double)max;
+	}
+	else {
+	    Rast_init_fp_range(&map_fp_range);
+	    Rast_read_fp_range(input_map_name, mapset, &map_fp_range);
+	    Rast_get_fp_range_min_max(&map_fp_range, &(map->min),
+				      &(map->max));
+	}
+    }
+    /* end opening and checking */
+
+    input_buffer = Rast_allocate_buf(input_data_type);
+
+    /* start reading */
+    G_message(_("Reading map <%s>"), input_map_name);
+
+    for (r = 0; r < map->nrows; ++r) {
+	G_percent(r, map->nrows, 2);
+
+	Rast_get_row(input_map_fd, input_buffer, r, input_data_type);
+	input_pointer = input_buffer;
+
+	for (c = 0; c < map->ncols; ++c)
+	    if (!Rast_is_null_value
+		(input_pointer + c * input_data_size, input_data_type))
+		switch (map->data_type) {
+		case CELL_TYPE:
+		    ((CELL **) map->map)[r][c] =
+			Rast_get_c_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case FCELL_TYPE:
+		    ((FCELL **) map->map)[r][c] =
+			Rast_get_f_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case DCELL_TYPE:
+		    ((DCELL **) map->map)[r][c] =
+			Rast_get_d_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		default:
+		    G_fatal_error(_("ram_open:Wrong internal data type"));
+		    break;
+		}
+    }				/*end for r */
+
+    G_free(input_buffer);
+    G_percent(r, map->nrows, 2);
+    Rast_close(input_map_fd);
+    return 0;
+}				/* end create floating point map */
+
+int ram_reset_map(MAP * map, int value)
+{
+    /*
+     * set all cells in the map to value
+     */
+    int r;
+
+    for (r = 0; r < map->nrows; ++r)
+	memset((map->map)[r], value, map->ncols * map->data_size);
+    return 0;
+}
+
+int ram_write_map(MAP * map, char *output_map_name,
+		  RASTER_MAP_TYPE output_data_type, int convert_to_null,
+		  double value)
+{
+    /* 
+     * write map to disk with output_map_name and output_data_type [CELL, FCELL, DCELL];
+     * if output_data_type = -1 than internal map type is used for output;
+     * if output map != -1 and types differ data_type, conversion is forced
+     * convert to null: check if convert to null a particular value in dataset;
+     */
+
+    int r, c;
+    int output_fd = 0;
+    struct History history;
+    void *row;
+
+    /* check for output format */
+    if (output_data_type == -1)
+	output_data_type = map->data_type;
+
+    if (output_data_type != map->data_type)
+	G_debug(1,
+		"ram_write:required map type and internal map type differs: conversion forced!");
+
+    G_message(_("Writing map <%s>"), output_map_name);
+    output_fd = Rast_open_new(output_map_name, output_data_type);
+
+    /* writing */
+    for (r = 0; r < map->nrows; ++r) {
+	G_percent(r, map->nrows, 2);
+
+	if (convert_to_null) {
+	    row = map->map[r];
+	    switch (map->data_type) {
+	    case CELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((CELL *) row)[c] == (CELL) value)
+			Rast_set_c_null_value(row + c * (map->data_size), 1);
+		break;
+	    case FCELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((FCELL *) row)[c] == (FCELL) value)
+			Rast_set_f_null_value(row + c * (map->data_size), 1);
+		break;
+	    case DCELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((DCELL *) row)[c] == (DCELL) value)
+			Rast_set_d_null_value(row + c * (map->data_size), 1);
+		break;
+	    default:
+		G_debug(1, "ram_null:Cannot convert to null at: %d %d", r, c);
+	    }
+	}
+
+	Rast_put_row(output_fd, (map->map)[r], output_data_type);
+    }
+    G_percent(r, map->nrows, 2);
+    Rast_close(output_fd);
+    Rast_short_history(output_map_name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(output_map_name, &history);
+    G_message(_("<%s> Done"), output_map_name);
+    return 0;
+}
+
+int ram_release_map(MAP *map)
+{
+    /* 
+     * free memory allocated for map, set pointer to null;
+     */
+    int r;
+
+    for (r = 0; r < map->nrows; ++r)
+	G_free((map->map)[r]);
+    G_free(map->map);
+    map = NULL;
+    return 0;
+}
+
+
+/* memory swap functions section */
+
+
+int seg_create_map(SEG * seg, int srows, int scols, int number_of_segs,
+		   RASTER_MAP_TYPE data_type)
+{
+    /* create segment  and returns pointer to it;
+     * seg must be declared first;
+     * parameters are stored in structure;
+     * seg: segment to be created;
+     * srows, scols segment size
+     * number of segs max number of segs stored in memory
+     * data_type to be created must be CELL, FCELL, DCELL;
+     */
+
+    char *filename;
+    int fd;
+    int local_number_of_segs;
+
+    seg->fd = -1;
+    seg->filename = NULL;
+    seg->map_name = NULL;
+    seg->mapset = NULL;
+    seg->data_type = data_type;
+    seg->nrows = Rast_window_rows();
+    seg->ncols = Rast_window_cols();
+
+    local_number_of_segs =
+	(seg->nrows / srows + 1) * (seg->ncols / scols + 1);
+    number_of_segs =
+	(number_of_segs >
+	 local_number_of_segs) ? local_number_of_segs : number_of_segs;
+
+    G_debug(3, "seg_creat:number of segments %d", number_of_segs);
+
+    switch (seg->data_type) {
+    case CELL_TYPE:
+	seg->data_size = sizeof(CELL);
+	break;
+    case FCELL_TYPE:
+	seg->data_size = sizeof(FCELL);
+	break;
+    case DCELL_TYPE:
+	seg->data_size = sizeof(DCELL);
+	break;
+    default:
+	G_fatal_error(_("seg_create: unrecognisabe data type"));
+    }
+
+    filename = G_tempfile();
+    fd = creat(filename, 0666);
+
+    if (0 >
+	segment_format(fd, seg->nrows, seg->ncols, srows, scols,
+		       seg->data_size)) {
+	close(fd);
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot format segment"));
+    }
+
+    close(fd);
+    if (0 > (fd = open(filename, 2))) {
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot re-open file"));
+    }
+
+    if (0 > (fd = segment_init(&(seg->seg), fd, number_of_segs))) {
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot init segment file or out of memory"));
+    }
+
+    seg->filename = G_store(filename);
+    seg->fd = fd;
+    return 0;
+}
+
+int seg_read_map(SEG * seg, char *input_map_name, int check_res,
+		 RASTER_MAP_TYPE check_data_type)
+{
+
+    /*
+     * Funciton read external map and put it in SEG structure (created with seg_create_map)
+     * map to be read can be of any data type, read map is converted if neccesary.
+     * input_map_name: name of the map to be read;
+     * seg: pointer to map stucture (created with create_map);
+     * check_res: [1]: check res correspondence between region and map [0 no check];
+     * check_data_type [CELL, FCELL, DCELL] check if reading map is of particular type, [-1] no check;
+     */
+
+    int input_fd;
+    int r, c;
+    char *mapset;
+    struct Cell_head cellhd, this_window;
+    char *maptypes[] = { "CELL", "FCELL", "DCELL" };
+    RASTER_MAP_TYPE input_data_type;
+    size_t input_data_size;
+    void *input_buffer = NULL;
+    void *target_buffer = NULL;
+    void *input_pointer = NULL;
+
+    /* checking if map exist */
+    mapset = (char *)G_find_raster2(input_map_name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("seg_read:Raster map <%s> not found"),
+		      input_map_name);
+    seg->mapset = mapset;
+
+    /* checking if region and input are the same */
+    G_get_window(&this_window);
+    Rast_get_cellhd(input_map_name, mapset, &cellhd);
+
+    /* check resolution equal anyinteger check;  equal 0 no check */
+    if (check_res)
+	if (this_window.ew_res != cellhd.ew_res ||
+	    this_window.ns_res != cellhd.ns_res)
+	    G_fatal_error(_("Region resolution and map %s resolution differs. \
+		Run g.region rast=%s to set proper region resolution"),
+			  input_map_name, input_map_name);
+
+    if (check_data_type != seg->data_type)
+	G_debug(1,
+		"ram_open:required map type and internal map type differs: conversion forced!");
+    input_data_type = Rast_map_type(input_map_name, mapset);
+    if (check_data_type != -1)
+	if (input_data_type != check_data_type)
+	    G_fatal_error(_("<%s> is not of type %s"),
+			  input_map_name, maptypes[check_data_type]);
+
+    input_fd = Rast_open_old(input_map_name, mapset);
+    input_data_size = Rast_cell_size(input_data_type);
+
+    {				/* reading range */
+	struct Range map_range;
+	struct FPRange map_fp_range;
+	int min, max;
+
+	if (input_data_type == CELL_TYPE) {
+	    Rast_init_range(&map_range);
+	    Rast_read_range(input_map_name, mapset, &map_range);
+	    Rast_get_range_min_max(&map_range, &min, &max);
+	    seg->min = (double)min;
+	    seg->max = (double)max;
+	}
+	else {
+	    Rast_init_fp_range(&map_fp_range);
+	    Rast_read_fp_range(input_map_name, mapset, &map_fp_range);
+	    Rast_get_fp_range_min_max(&map_fp_range, &(seg->min),
+				      &(seg->max));
+	}
+    }
+
+    /* end opening and checking */
+
+    G_message(_("Reading map <%s>"), input_map_name);
+    input_buffer = Rast_allocate_buf(input_data_type);
+
+    target_buffer = Rast_allocate_buf(seg->data_type);
+
+    for (r = 0; r < seg->nrows; ++r) {
+	G_percent(r, seg->nrows, 2);
+	Rast_get_row(input_fd, input_buffer, r, input_data_type);
+	input_pointer = input_buffer;
+	memset(target_buffer, 0, seg->ncols * seg->data_size);
+
+	for (c = 0; c < seg->ncols; ++c)
+	    if (!Rast_is_null_value
+		(input_pointer + c * input_data_size, input_data_type)) {
+		switch (seg->data_type) {
+		case CELL_TYPE:
+		    ((CELL *) target_buffer)[c] =
+			Rast_get_c_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case FCELL_TYPE:
+		    ((FCELL *) target_buffer)[c] =
+			Rast_get_f_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case DCELL_TYPE:
+		    ((DCELL *) target_buffer)[c] =
+			Rast_get_d_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		default:
+		    G_fatal_error(_("Wrong internal data type"));
+		    break;
+		}
+	    }
+
+	if (0 > segment_put_row(&(seg->seg), target_buffer, r)) {
+	    G_free(input_buffer);
+	    G_free(target_buffer);
+	    Rast_close(input_fd);
+	    G_fatal_error(_("seg_read: Cannot segment put row %d for map %s"),
+			  r, input_map_name);
+	}
+    }				/* end for row */
+
+    G_percent(r, seg->nrows, 2);
+    Rast_close(input_fd);
+    G_free(input_buffer);
+    G_free(target_buffer);
+
+    seg->map_name = G_store(input_map_name);
+    seg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int seg_reset_map(SEG * seg, int value)
+{
+    /*
+     * set all cells in the map to value
+     */
+    int r, c;
+
+    for (r = 0; r < seg->nrows; ++r)
+	for (c = 0; c < seg->ncols; ++c)
+	    segment_put(&(seg->seg), &value, r, c);
+
+    return 0;
+}
+
+int seg_write_map(SEG * seg, char *output_map_name,
+		  RASTER_MAP_TYPE output_data_type, int convert_to_null,
+		  double value)
+{
+    /* 
+     * write seg to disk with output_map_name and output_data_type [CELL, FCELL, DCELL];
+     * if output_data_type = -1 than internal map type is used for output;
+     * if output map != -1 and types differ data_type, conversion is forced
+     * convert to null: check if convert to null a particular value in dataset;
+     */
+    int output_fd;
+    int r, c;
+    void *output_buffer;
+    void *row;
+    struct History history;
+
+    /* check for output format */
+    if (output_data_type == -1)
+	output_data_type = seg->data_type;
+
+    if (output_data_type != seg->data_type)
+	G_debug(1,
+		"ram_write:required map type and internal map type differs: conversion forced!");
+
+    G_message(_("Writing map <%s>"), output_map_name);
+    output_fd = Rast_open_new(output_map_name, output_data_type);
+    output_buffer = Rast_allocate_buf(output_data_type);
+    segment_flush(&(seg->seg));
+
+    /* writing */
+    for (r = 0; r < seg->nrows; ++r) {
+
+	G_percent(r, seg->nrows, 2);
+	if (0 > segment_get_row(&(seg->seg), output_buffer, r))
+	    G_warning(_("seg_write: Cannot segment read row %d for map %s"),
+		      r, output_map_name);
+
+	if (convert_to_null) {
+
+	    row = output_buffer;
+	    switch (seg->data_type) {
+	    case CELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((CELL *) output_buffer)[c] == (CELL) value)
+			Rast_set_c_null_value(row + c * (seg->data_size), 1);
+		break;
+	    case FCELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((FCELL *) output_buffer)[c] == (FCELL) value)
+			Rast_set_f_null_value(row + c * (seg->data_size), 1);
+		break;
+	    case DCELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((DCELL *) output_buffer)[c] == (DCELL) value)
+			Rast_set_d_null_value(row + c * (seg->data_size), 1);
+		break;
+	    default:
+		G_warning(_("ram_null:Cannot convert to null at: %d %d"), r,
+			  c);
+	    }
+	}
+	Rast_put_row(output_fd, output_buffer, output_data_type);
+    }
+
+    G_percent(r, seg->nrows, 2);
+    G_free(output_buffer);
+    Rast_close(output_fd);
+    Rast_short_history(output_map_name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(output_map_name, &history);
+    G_message(_("%s Done"), output_map_name);
+
+    return 0;
+}
+
+int seg_release_map(SEG * seg)
+{
+    /* 
+     * release segment close files, set pointers to null;
+     */
+    segment_release(&(seg->seg));
+    close(seg->fd);
+    unlink(seg->filename);
+
+    if (seg->map_name)
+	G_free(seg->map_name);
+    if (seg->mapset)
+	G_free(seg->mapset);
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.channel/io.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/io.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/io.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/segment.h>
+
+#define NOT_IN_REGION(x) (r + nextr[(x)] < 0 || r + nextr[(x)] > (nrows - 1) || \
+                          c + nextc[(x)] < 0 || c + nextc[(x)] > (ncols - 1))
+#define NR(x) (r + nextr[(x)])
+#define NC(x) (c + nextc[(x)])
+#define INDEX(r,c) ((r) * ncols + (c))
+#define DIAG(x) (((x) + 4) > 8 ? ((x) - 4) : ((x) + 4))
+
+#define SROWS 256
+#define SCOLS 256
+
+typedef struct {
+	void **map; /* matrix of data */
+	double min, max; /* data range : may requre casting */
+	int nrows, ncols;
+	char *map_name; /* map name, unused */
+	RASTER_MAP_TYPE data_type; /* type of data */
+	size_t data_size; /* type of data */
+} MAP;
+
+typedef struct {
+	SEGMENT seg;		/* segmented data store */
+	int fd;					/* segment temporary file name descriptor */
+	char *filename; /* segment temporary file name */
+	char *map_name; /* map name converted to segment */
+	char *mapset;
+	int nrows, ncols; /* store nrows and rcols */
+	RASTER_MAP_TYPE data_type; /* data type of the map */
+	size_t data_size; /* size of cell returned by sizeof */
+	double min, max; /* data range */
+} SEG;
+
+
+/* all in ram functions */
+int ram_create_map(MAP *, RASTER_MAP_TYPE);
+int ram_read_map(MAP *, char *, int, RASTER_MAP_TYPE);
+int ram_reset_map(MAP *, int);
+int ram_write_map(MAP *, char *, RASTER_MAP_TYPE, int, double);
+int ram_release_map(MAP *);
+int ram_destory_map(MAP *);
+
+/* memory swap functions */
+int seg_create_map(SEG *, int, int, int, RASTER_MAP_TYPE);
+int seg_read_map(SEG *, char *, int, RASTER_MAP_TYPE);
+int seg_reset_map (SEG *, int);
+int seg_write_map(SEG *, char *, RASTER_MAP_TYPE, int, double);
+int seg_release_map(SEG *);
+

Added: grass-addons/grass7/grass7/raster/r.stream.channel/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,57 @@
+#include "io.h"
+#include "local_vars.h"
+
+int free_attributes(int number_of_streams);
+
+
+int ram_build_streamlines(CELL **streams, CELL **dirs, FCELL **elevation,
+			  int number_of_streams);
+int ram_number_of_streams(CELL **streams, CELL **dirs);
+int ram_find_contributing_cell(int r, int c, CELL **dirs, FCELL **elevation);
+
+int ram_set_null_output(DCELL **output);
+int ram_calculate_identifiers(CELL **identifier, int number_of_streams,
+			      int downstream);
+int ram_calculate_difference(DCELL **output, int number_of_streams,
+			     int downstream);
+int ram_calculate_drop(DCELL **output, int number_of_streams, int downstream);
+int ram_calculate_local_distance(DCELL **output, int number_of_streams,
+				 int downstream);
+int ram_calculate_distance(DCELL **output, int number_of_streams,
+			   int downstream);
+int ram_calculate_cell(DCELL **output, int number_of_streams, int downstream);
+int ram_calculate_local_gradient(DCELL **output, int number_of_streams,
+				 int downstream);
+int ram_calculate_gradient(DCELL **output, int number_of_streams,
+			   int downstream);
+int ram_calculate_curvature(DCELL **output, int number_of_streams,
+			    int downstream);
+
+
+
+int seg_build_streamlines(SEGMENT *streams, SEGMENT *dirs,
+			  SEGMENT *elevation, int number_of_streams);
+int seg_number_of_streams(SEGMENT *streams, SEGMENT *dirs);
+
+int seg_find_contributing_cell(int r, int c, SEGMENT *dirs,
+			       SEGMENT *elevation);
+
+int seg_set_null_output(SEGMENT *output);
+int seg_calculate_identifiers(SEGMENT *identifier, int number_of_streams,
+			      int downstream);
+int seg_calculate_difference(SEGMENT *output, int number_of_streams,
+			     int downstream);
+int seg_calculate_drop(SEGMENT *output, int number_of_streams,
+		       int downstream);
+int seg_calculate_local_distance(SEGMENT *output, int number_of_streams,
+				 int downstream);
+int seg_calculate_distance(SEGMENT *output, int number_of_streams,
+			   int downstream);
+int seg_calculate_cell(SEGMENT *output, int number_of_streams,
+		       int downstream);
+int seg_calculate_local_gradient(SEGMENT *output, int number_of_streams,
+				 int downstream);
+int seg_calculate_gradient(SEGMENT *output, int number_of_streams,
+			   int downstream);
+int seg_calculate_curvature(SEGMENT *output, int number_of_streams,
+			    int downstream);

Added: grass-addons/grass7/grass7/raster/r.stream.channel/local_vars.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/local_vars.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/local_vars.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+
+#define SQRT2 1.414214
+	
+
+	
+typedef struct {
+	int stream_num;
+	int number_of_cells;
+	int order;
+	unsigned long int * points;
+	float * elevation;
+	double * distance;
+	unsigned int init_r;
+	unsigned int init_c;
+} STREAM;	
+
+
+#ifdef MAIN
+#	define GLOBAL
+#else
+#	define GLOBAL extern
+#endif
+
+GLOBAL int nextr[9];
+GLOBAL int nextc[9];
+
+GLOBAL int nrows, ncols; 
+GLOBAL STREAM* stream_attributes;
+
+GLOBAL struct Cell_head window;
+
+

Added: grass-addons/grass7/grass7/raster/r.stream.channel/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,340 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.stream.channel
+ * AUTHOR(S):    Jarek Jasiewicz jarekj amu.edu.pl
+ *               
+ * PURPOSE:      Program calculate some channel properities:
+ * 							 local elevation change, curvature along stream,
+ * 							 distance to channel init/join, elevation below channel init, 
+ * 							 optionally distance to outlet, elevation above outlet;
+        
+ * COPYRIGHT:    (C) 2002,2010 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *   	    	 	  License (>=v2). Read the file COPYING that comes with GRASS
+ *   	    	 	  for details.
+ *
+ *****************************************************************************/
+#define MAIN
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int nextr[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+int nextc[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+
+
+int main(int argc, char *argv[])
+{
+
+    /*
+       IO output[] = {
+       {"local_diff",NO,"Local elevation difference"},
+       {"out_dist",NO,"Upstream distance form init"},
+     */
+
+    struct GModule *module;
+    struct Option *in_dir_opt,	/* options */
+     *in_stm_opt,
+	*in_elev_opt,
+	*out_identifier_opt,
+	*out_distance_opt,
+	*out_difference_opt,
+	*out_gradient_opt, *out_curvature_opt, *opt_swapsize;
+
+    struct Flag *flag_segmentation,
+	*flag_local, *flag_cells, *flag_downstream;
+
+    char *method_name[] = { "UPSTREAM", "DOWNSTREAM" };
+    int number_of_segs;
+    int number_of_streams;
+    int segmentation, downstream, local, cells;	/*flags */
+
+    /* initialize GIS environment */
+    G_gisinit(argv[0]);
+
+    /* initialize module */
+    module = G_define_module();
+    G_add_keyword("Horton statisctics");
+    module->description =
+	_("Calculate local parameters for individual streams");
+    G_add_keyword("Stream parameters");
+    G_add_keyword("Stream gradient");
+    G_add_keyword("Stream curvature");
+
+    in_stm_opt = G_define_standard_option(G_OPT_R_INPUT);
+    in_stm_opt->key = "streams";
+    in_stm_opt->description = "Name of streams mask input map";
+
+    in_dir_opt = G_define_standard_option(G_OPT_R_INPUT);
+    in_dir_opt->key = "dirs";
+    in_dir_opt->description = "Name of flow direction input map";
+
+    in_elev_opt = G_define_standard_option(G_OPT_R_INPUT);
+    in_elev_opt->key = "elevation";
+    in_elev_opt->description = "Name of elevation map";
+
+    out_identifier_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_identifier_opt->key = "identifier";
+    out_identifier_opt->required = NO;
+    out_identifier_opt->description = "Unique identifier for stream";
+
+    out_distance_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_distance_opt->key = "distance";
+    out_distance_opt->required = NO;
+    out_distance_opt->description = "Distance from init/join/outlet";
+
+    out_difference_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_difference_opt->key = "difference";
+    out_difference_opt->required = NO;
+    out_difference_opt->description =
+	"Elevation differecne from init/join/outlet";
+
+    out_gradient_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_gradient_opt->key = "gradient";
+    out_gradient_opt->required = NO;
+    out_gradient_opt->description =
+	"Mean gradient of stream from init/join/outlet";
+
+    out_curvature_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_curvature_opt->key = "curvature";
+    out_curvature_opt->required = NO;
+    out_curvature_opt->description = "Local stream curvature";
+
+    opt_swapsize = G_define_option();
+    opt_swapsize->key = "memory";
+    opt_swapsize->type = TYPE_INTEGER;
+    opt_swapsize->answer = "300";
+    opt_swapsize->description = _("Max memory used in memory swap mode (MB)");
+    opt_swapsize->guisection = _("Optional");
+
+    flag_downstream = G_define_flag();
+    flag_downstream->key = 'd';
+    flag_downstream->description =
+	_("Calculate parameters from outlet (downstream values)");
+
+    flag_local = G_define_flag();
+    flag_local->key = 'l';
+    flag_local->description = _("Calculate local values (for current cell)");
+
+    flag_cells = G_define_flag();
+    flag_cells->key = 'c';
+    flag_cells->description = _("Calculate distance in cell (ignored local)");
+
+    flag_segmentation = G_define_flag();
+    flag_segmentation->key = 'm';
+    flag_segmentation->description = _("Use memory swap (operation is slow)");
+
+    if (G_parser(argc, argv))	/* parser */
+	exit(EXIT_FAILURE);
+
+    segmentation = (flag_segmentation->answer != 0);
+    downstream = (flag_downstream->answer != 0);
+
+    if (!out_identifier_opt->answer &&
+	!out_distance_opt->answer &&
+	!out_difference_opt->answer &&
+	!out_gradient_opt->answer && !out_curvature_opt->answer)
+	G_fatal_error(_("You must select at least one output maps"));
+
+    local = (flag_local->answer != 0);
+    cells = (flag_cells->answer != 0);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    G_get_window(&window);
+    G_begin_distance_calculations();
+
+    if (out_identifier_opt->answer)
+	if (G_legal_filename(out_identifier_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal difference map name"),
+			  out_identifier_opt->answer);
+
+    if (out_difference_opt->answer)
+	if (G_legal_filename(out_difference_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal difference map name"),
+			  out_difference_opt->answer);
+
+    if (out_distance_opt->answer)
+	if (G_legal_filename(out_distance_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal distance map name"),
+			  out_distance_opt->answer);
+
+    if (out_gradient_opt->answer)
+	if (G_legal_filename(out_gradient_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal gradient map name"),
+			  out_gradient_opt->answer);
+
+    if (out_curvature_opt->answer)
+	if (G_legal_filename(out_curvature_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal gradient map name"),
+			  out_curvature_opt->answer);
+
+    if (!segmentation) {
+	MAP map_dirs, map_streams, map_elevation, map_output, map_identifier;
+	CELL **streams, **dirs, **identifier = NULL;
+	FCELL **elevation;
+	DCELL **output;
+
+	G_message(_("ALL IN RAM CALCULATION - DIRECTION: %s"),
+		  method_name[downstream]);
+	ram_create_map(&map_streams, CELL_TYPE);
+	ram_read_map(&map_streams, in_stm_opt->answer, 1, CELL_TYPE);
+	ram_create_map(&map_dirs, CELL_TYPE);
+	ram_read_map(&map_dirs, in_dir_opt->answer, 1, CELL_TYPE);
+	ram_create_map(&map_elevation, FCELL_TYPE);
+	ram_read_map(&map_elevation, in_elev_opt->answer, 0, -1);
+
+	streams = (CELL **) map_streams.map;
+	dirs = (CELL **) map_dirs.map;
+	elevation = (FCELL **) map_elevation.map;
+
+	number_of_streams = ram_number_of_streams(streams, dirs) + 1;
+	ram_build_streamlines(streams, dirs, elevation, number_of_streams);
+	ram_release_map(&map_streams);
+	ram_release_map(&map_dirs);
+	ram_create_map(&map_output, DCELL_TYPE);
+	output = (DCELL **) map_output.map;	/* one output for all maps */
+
+	if (out_identifier_opt->answer) {
+	    ram_create_map(&map_identifier, CELL_TYPE);
+	    identifier = (CELL **) map_identifier.map;
+	    ram_calculate_identifiers(identifier, number_of_streams,
+				      downstream);
+	    ram_write_map(&map_identifier, out_identifier_opt->answer,
+			  CELL_TYPE, 1, 0);
+	    ram_release_map(&map_identifier);
+	}
+
+	if (out_difference_opt->answer) {
+	    ram_set_null_output(output);
+	    if (local)
+		ram_calculate_difference(output, number_of_streams,
+					 downstream);
+	    else
+		ram_calculate_drop(output, number_of_streams, downstream);
+	    ram_write_map(&map_output, out_difference_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	if (out_distance_opt->answer) {
+	    ram_set_null_output(output);
+	    if (local && !cells)
+		ram_calculate_local_distance(output, number_of_streams,
+					     downstream);
+	    if (!local && !cells)
+		ram_calculate_distance(output, number_of_streams, downstream);
+	    if (cells)
+		ram_calculate_cell(output, number_of_streams, downstream);
+	    ram_write_map(&map_output, out_distance_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	if (out_gradient_opt->answer) {
+	    ram_set_null_output(output);
+	    if (local)
+		ram_calculate_local_gradient(output, number_of_streams,
+					     downstream);
+	    else
+		ram_calculate_gradient(output, number_of_streams, downstream);
+	    ram_write_map(&map_output, out_gradient_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	if (out_curvature_opt->answer) {
+	    ram_set_null_output(output);
+	    ram_calculate_curvature(output, number_of_streams, downstream);
+	    ram_write_map(&map_output, out_curvature_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	ram_release_map(&map_output);
+    }
+
+
+    if (segmentation) {
+	SEG map_dirs, map_streams, map_elevation, map_output, map_identifier;
+	SEGMENT *streams, *dirs, *elevation, *output, *identifier;
+
+	G_message(_("SEGMENT CALCULATION: MAY TAKE SOME TIME- DIRECTION: %s"),
+		  method_name[downstream]);
+
+	number_of_segs = (int)atof(opt_swapsize->answer);
+	number_of_segs = number_of_segs < 32 ? (int)(32 / 0.18) : number_of_segs / 0.18;
+
+	seg_create_map(&map_streams, SROWS, SCOLS, number_of_segs, CELL_TYPE);
+	seg_read_map(&map_streams, in_stm_opt->answer, 1, CELL_TYPE);
+	seg_create_map(&map_dirs, SROWS, SCOLS, number_of_segs, CELL_TYPE);
+	seg_read_map(&map_dirs, in_dir_opt->answer, 1, CELL_TYPE);
+	seg_create_map(&map_elevation, SROWS, SCOLS, number_of_segs,
+		       FCELL_TYPE);
+	seg_read_map(&map_elevation, in_elev_opt->answer, 0, -1);
+
+	streams = &map_streams.seg;
+	dirs = &map_dirs.seg;
+	elevation = &map_elevation.seg;
+
+	number_of_streams = seg_number_of_streams(streams, dirs) + 1;
+	seg_build_streamlines(streams, dirs, elevation, number_of_streams);
+	seg_release_map(&map_streams);
+	seg_release_map(&map_dirs);
+	seg_create_map(&map_output, SROWS, SCOLS, number_of_segs, DCELL_TYPE);
+	output = &map_output.seg;	/* one output for all maps */
+
+	if (out_identifier_opt->answer) {
+	    seg_create_map(&map_identifier, SROWS, SCOLS, number_of_segs,
+			   CELL_TYPE);
+	    identifier = &map_identifier.seg;
+	    seg_calculate_identifiers(identifier, number_of_streams,
+				      downstream);
+	    seg_write_map(&map_identifier, out_identifier_opt->answer,
+			  CELL_TYPE, 1, 0);
+	    seg_release_map(&map_identifier);
+	}
+
+	if (out_difference_opt->answer) {
+	    seg_set_null_output(output);
+	    if (local)
+		seg_calculate_difference(output, number_of_streams,
+					 downstream);
+	    else
+		seg_calculate_drop(output, number_of_streams, downstream);
+	    seg_write_map(&map_output, out_difference_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	if (out_distance_opt->answer) {
+	    seg_set_null_output(output);
+	    if (local && !cells)
+		seg_calculate_local_distance(output, number_of_streams,
+					     downstream);
+	    if (!local && !cells)
+		seg_calculate_distance(output, number_of_streams, downstream);
+	    if (cells)
+		seg_calculate_cell(output, number_of_streams, downstream);
+	    seg_write_map(&map_output, out_distance_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	if (out_gradient_opt->answer) {
+	    seg_set_null_output(output);
+	    if (local)
+		seg_calculate_local_gradient(output, number_of_streams,
+					     downstream);
+	    else
+		seg_calculate_gradient(output, number_of_streams, downstream);
+	    seg_write_map(&map_output, out_gradient_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	if (out_curvature_opt->answer) {
+	    seg_set_null_output(output);
+	    seg_calculate_curvature(output, number_of_streams, downstream);
+	    seg_write_map(&map_output, out_curvature_opt->answer, DCELL_TYPE,
+			  0, 0);
+	}
+
+	seg_release_map(&map_output);
+    }
+    free_attributes(number_of_streams);
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.stream.channel/r.stream.channel.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/r.stream.channel.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/r.stream.channel.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,136 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>-l</b></dt>
+<dd>Calculate local values. See output for detials.</dd>
+<dt><b>-c</b></dt>
+<dd>Calculate distance in cells instead of meters. See output for detials.</dd>
+<dt><b>-d</b></dt>
+<dd>Calculate downstream distance (from current cell DOWNSTREAM to outlet/join).
+Default is upstream (from current cell upstream to init/join.</dd>
+<dt><b>-m</b></dt>
+<dd>Only for very large data sets. Use segment library to optimize memory
+consumption during analysis</dd>
+<dt><b>stream</b></dt>
+<dd>Stream network: name of input stream map. Map may be ordered according one
+of the r.stream.order ordering system as well as unordered (with origilan stream
+identifiers)  Because streams network produced by r.watershed and
+r.stream.extract may slighty differ in detail it is required to use both stream
+and direction map produced by the same module. Stream background shall have NULL
+value or zero value. Background values of NULL are by default produced by
+r.watershed and r.stream.extract. If not 0 or NULL use <a
+href="r.mapcalc.html">r.mapcalc</a> to set background values to null.  
+</dd>
+<dt><b>dir</b></dt>
+<dd>Flow direction: name of input direction map produced by r.watershed or
+r.stream.extract. If r.stream.extract output map is used, it only has non-NULL
+values in places where streams occur. NULL (nodata) cells are ignored, zero and
+negative values are valid direction data if they vary from -8 to 8 (CCW from
+East in steps of 45 degrees). Direction map shall be of type CELL values. Region
+resolution and map resoultion must be the same. 
+Also <em>stream</em> network map must have the same resolution. It is checked by
+default. If resolutions differ the module informs about it and stops. Region
+boundary and maps boundary may be differ but it may lead to unexpected
+results.</dd>
+<dt><b>elevation</b></dt>
+<dd>Elevation: name of input elevation map. Map can be of type CELL, FCELL or
+DCELL. It is not restricted to resolution of region settings as streams and
+dirs.</dd>
+</dl>
+<h2>OUTPUTS</h2>
+<dl>
+<dt><b>distance</b></dt>
+<dd>Upstream distance of current cell to the init/join. Flag modifications: <br>
+<b>d:</b> downstream distance of current cell to the join/outlet;<br>
+<b>l:</b> local distance between current cell and next cell. In most cases cell
+resolution and sqrt2 of cell resolution. usefull when projection is LL or NS and
+WE resolutions differs. Flag d ignored<br>
+<b>c:</b> distance in cells. Map is written as double. Use mapcalc to convetrt
+to integer. Flags l and d ignored.<br>
+</dd>
+<dt><b>difference</b></dt>
+<dd>Upstream elevation difference between current cell to the init/join. It we
+need to calculate parameters different than elevation. If we need to calculate
+different parameters than elevation along streams (for example precipitation or
+so) use neccesary map as elevation. Flag modifications: <br>
+<b>d:</b> downstream difference of current cell to the join/outlet;<br>
+<b>l:</b> local difference between current cell and next cell. With flag
+calculates difference between previous cell and current cell<br>
+<b>c:</b> Ignored.
+</dd>
+<dt><b>gradient</b></dt>
+<dd>Upstream mean gradient between current cell and the init/join.  Flag
+modifications: <br>
+<b>d:</b> downstream mean gradient between current cell and the the
+join/outlet;<br>
+<b>l:</b> local gradient between current cell and next cell. Flag d ignored<br>
+<b>c:</b> Ignored.
+</dd>
+<dt><b>curvature</b></dt>
+<dd>Local stream course curvature  of current cell. Calculated according
+formula: <i>first_derivative/(1-second_derivative<sup>2</sup>)<sup>3/2</sup></i>
+Flag modifications: <br>
+<b>d:</b> ignored;<br>
+<b>l:</b> Ignored.<br>
+<b>c:</b> Ignored.
+</dd>
+<dt><b>identifier</b></dt>
+<dd> Integer map: In ordered stream network there are more than one segment
+(segment: a part of the network where order ramains unchanged) with the same
+order. To identify particular segments (for further analysis) every segment
+recive his unique identifier.</dd>
+</dl>
+
+<h2>DESCRIPTION</h2>
+<p>
+Module r.stream.channel is prepared to calculate some local properties of the
+stream network. It is suplementary module for r.stream.order, and
+r.stream.distance to investigate channel subsystem. For slope subsystem
+parameters is r.stream.slope. It may use ordered or unordered network. It
+calculate parameters for every segment between it init to outlet/join to the
+next stream. it also may calculate parameters between outlet and segment's init.
+It can calculate parameters for every orders but best results are for these
+orders where order remains unchanged from stream init to natural outlet (Hack
+and Horton ordering).
+<p>
+
+<h2>EXAMPLE</h2>
+
+This example shows how to visualise the change of gradient map along the main
+stream of the catchment:
+
+<div class="code"><pre>
+r.watershed elevation=elevation.10m treshold=1000 stream=streams drainage=dirs
+r.stream.order streams=streams dirs=dirs hack=hack
+r.stream.channel streams=hack dirs=dirs elevation=elevation.10m
+identifier=stream_identifier gradient=stream_gradient distance=stream_distance
+#495 is a stream identifier. May be different in different situaltion
+r.mapcalc stgrad=if(stream_identifier==495,float(stream_gradient),null())
+r.mapcalc stdist=if(stream_identifier==495,float(stream_distance),null())
+
+#the rest data processing in R
+R
+library(spgrass6)
+r=readRAST6(c("stdist","stgrad"),NODATA=-9999)
+p=subset(r at data,!is.na(r at data$dist))
+sorted=p[order(p$stdist),]
+plot(sorted,stdist~stgrad,type="l")
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.watershed.html">r.watershed</a>,
+<a href="r.stream.extract.html">r.stream.extract</a>,
+<a href="r.stream.order.html">r.stream.order</a>,
+<a href="r.stream.basins.html">r.stream.basins</a>,
+<a href="r.stream.slope.html">r.stream.slope</a>,
+<a href="r.stream.stats.html">r.stream.stats</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+</em>
+
+<h2>AUTHOR</h2>
+Jarek Jasiewicz, Adam Mickiewicz University, Geoecology and Geoinformation
+Institute.
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>
+

Added: grass-addons/grass7/grass7/raster/r.stream.channel/stream_topology.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/stream_topology.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/stream_topology.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,424 @@
+#include "local_proto.h"
+double get_distance(int r, int c, int d)
+{
+    double northing, easting, next_northing, next_easting;
+    int next_r, next_c;
+
+    next_r = NR(d);
+    next_c = NC(d);
+    northing = window.north - (r + .5) * window.ns_res;
+    easting = window.west + (c + .5) * window.ew_res;
+    next_northing = window.north - (next_r + .5) * window.ns_res;
+    next_easting = window.west + (next_c + .5) * window.ew_res;
+    return G_distance(easting, northing, next_easting, next_northing);
+}
+
+int ram_trib_nums(int r, int c, CELL ** streams, CELL ** dirs)
+{				/* calculate number of tributuaries */
+
+    int trib_num = 0;
+    int i, j;
+    int next_r, next_c;
+
+    for (i = 1; i < 9; ++i) {
+	if (NOT_IN_REGION(i))
+	    continue;
+
+	j = DIAG(i);
+	next_r = NR(i);
+	next_c = NC(i);
+
+	if (streams[next_r][next_c] > 0 && dirs[next_r][next_c] == j)
+	    trib_num++;
+    }
+
+    if (trib_num > 1)
+	for (i = 1; i < 9; ++i) {
+	    if (NOT_IN_REGION(i))
+		continue;
+
+	    j = DIAG(i);
+	    next_r = NR(i);
+	    next_c = NC(i);
+
+	    if (streams[next_r][next_c] == streams[r][c] &&
+		dirs[next_r][next_c] == j)
+		trib_num--;
+	}
+
+    if (trib_num > 5)
+	G_fatal_error(_("Error finding inits. Stream and direction maps probably do not match..."));
+    if (trib_num > 3)
+	G_warning(_("Stream network may be too dense..."));
+
+    return trib_num;
+}				/* end trib_num */
+
+
+
+int ram_number_of_streams(CELL **streams, CELL **dirs)
+{
+    int r, c;
+    int stream_num = 0;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c)
+	    if (streams[r][c] > 0)
+		if (ram_trib_nums(r, c, streams, dirs) != 1)
+		    stream_num++;
+    return stream_num;
+}
+
+int ram_build_streamlines(CELL **streams, CELL **dirs, FCELL **elevation,
+			  int number_of_streams)
+{
+    int r, c, i;
+    int d, next_d;
+    int prev_r, prev_c;
+    int stream_num = 1, cell_num = 0;
+    int contrib_cell;
+    STREAM *SA;
+
+    stream_num = 1;
+
+    Rast_get_window(&window);
+
+    stream_attributes =
+	(STREAM *) G_malloc(number_of_streams * sizeof(STREAM));
+    G_message("Finding inits...");
+    SA = stream_attributes;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c)
+	    if (streams[r][c])
+		if (ram_trib_nums(r, c, streams, dirs) != 1) {	/* adding inits */
+		    if (stream_num > number_of_streams)
+			G_fatal_error(_("Error finding inits. Stream and direction maps probably do not match..."));
+
+		    SA[stream_num].stream_num = stream_num;
+		    SA[stream_num].init_r = r;
+		    SA[stream_num++].init_c = c;
+		}
+
+    for (i = 1; i < stream_num; ++i) {
+
+	r = SA[i].init_r;
+	c = SA[i].init_c;
+	SA[i].order = streams[r][c];
+	SA[i].number_of_cells = 0;
+	do {
+
+	    SA[i].number_of_cells++;
+	    d = abs(dirs[r][c]);
+	    if (NOT_IN_REGION(d) || d == 0)
+		break;
+	    r = NR(d);
+	    c = NC(d);
+	} while (streams[r][c] == SA[i].order);
+
+	SA[i].number_of_cells += 2;	/* add two extra points for init+ and outlet+ */
+    }
+
+    for (i = 1; i < number_of_streams; ++i) {
+
+	SA[i].points = (unsigned long int *)
+	    G_malloc((SA[i].number_of_cells) * sizeof(unsigned long int));
+	SA[i].elevation = (float *)
+	    G_malloc((SA[i].number_of_cells) * sizeof(float));
+	SA[i].distance = (double *)
+	    G_malloc((SA[i].number_of_cells) * sizeof(double));
+
+	r = SA[i].init_r;
+	c = SA[i].init_c;
+	contrib_cell = ram_find_contributing_cell(r, c, dirs, elevation);
+	prev_r = NR(contrib_cell);
+	prev_c = NC(contrib_cell);
+
+	/* add one point contributing to init to calculate parameters */
+	/* what to do if there is no contributing points? */
+	SA[i].points[0] = (contrib_cell == 0) ? -1 : INDEX(prev_r, prev_c);
+	SA[i].elevation[0] = (contrib_cell == 0) ? -99999 :
+	    elevation[prev_r][prev_c];
+	d = (contrib_cell == 0) ? dirs[r][c] : dirs[prev_r][prev_c];
+	SA[i].distance[0] = (contrib_cell == 0) ? get_distance(r, c, d) :
+	    get_distance(prev_r, prev_c, d);
+
+	SA[i].points[1] = INDEX(r, c);
+	SA[i].elevation[1] = elevation[r][c];
+	d = abs(dirs[r][c]);
+	SA[i].distance[1] = get_distance(r, c, d);
+
+	cell_num = 2;
+	do {
+	    d = abs(dirs[r][c]);
+
+	    if (NOT_IN_REGION(d) || d == 0) {
+		SA[i].points[cell_num] = -1;
+		SA[i].distance[cell_num] = SA[i].distance[cell_num - 1];
+		SA[i].elevation[cell_num] =
+		    2 * SA[i].elevation[cell_num - 1] -
+		    SA[i].elevation[cell_num - 2];
+		break;
+	    }
+	    r = NR(d);
+	    c = NC(d);
+	    SA[i].points[cell_num] = INDEX(r, c);
+	    SA[i].elevation[cell_num] = elevation[r][c];
+	    next_d = (abs(dirs[r][c]) == 0) ? d : abs(dirs[r][c]);
+	    SA[i].distance[cell_num] = get_distance(r, c, next_d);
+	    cell_num++;
+	    if (cell_num > SA[i].number_of_cells)
+		G_fatal_error(_("To much points in stream line..."));
+	} while (streams[r][c] == SA[i].order);
+
+	if (SA[i].elevation[0] == -99999)
+	    SA[i].elevation[0] = 2 * SA[i].elevation[1] - SA[i].elevation[2];
+    }
+
+    return 0;
+}
+
+int ram_find_contributing_cell(int r, int c, CELL **dirs, FCELL **elevation)
+{
+    int i, j = 0;
+    int next_r, next_c;
+    float elev_min = 9999;
+
+    for (i = 1; i < 9; ++i) {
+	if (NOT_IN_REGION(i))
+	    continue;
+	next_r = NR(i);
+	next_c = NC(i);
+	if (dirs[next_r][next_c] == DIAG(i) &&
+	    elevation[next_r][next_c] < elev_min) {
+	    elev_min = elevation[next_r][next_c];
+	    j = i;
+	}
+    }
+
+    return j;
+}
+
+int seg_trib_nums(int r, int c, SEGMENT * streams, SEGMENT * dirs)
+{				/* calculate number of tributuaries */
+
+    int trib_num = 0;
+    int i, j;
+    int next_r, next_c;
+    int streams_cell, streams_next_cell, dirs_next_cell;
+
+    segment_get(streams, &streams_cell, r, c);
+    for (i = 1; i < 9; ++i) {
+	if (NOT_IN_REGION(i))
+	    continue;
+
+	j = DIAG(i);
+	next_r = NR(i);
+	next_c = NC(i);
+	segment_get(streams, &streams_next_cell, next_r, next_c);
+	segment_get(dirs, &dirs_next_cell, next_r, next_c);
+	if (streams_next_cell > 0 && dirs_next_cell == j)
+	    trib_num++;
+    }
+
+    if (trib_num > 1)
+	for (i = 1; i < 9; ++i) {
+	    if (NOT_IN_REGION(i))
+		continue;
+
+	    j = DIAG(i);
+	    next_r = NR(i);
+	    next_c = NC(i);
+	    segment_get(streams, &streams_next_cell, next_r, next_c);
+	    segment_get(dirs, &dirs_next_cell, next_r, next_c);
+	    if (streams_next_cell == streams_cell && dirs_next_cell == j)
+		trib_num--;
+	}
+
+    if (trib_num > 5)
+	G_fatal_error(_("Error finding inits. Stream and direction maps probably do not match..."));
+    if (trib_num > 3)
+	G_warning(_("Stream network may be too dense..."));
+
+    return trib_num;
+}				/* end trib_num */
+
+int seg_number_of_streams(SEGMENT *streams, SEGMENT *dirs)
+{
+    int r, c;
+    int stream_num = 0;
+    int streams_cell;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+	    segment_get(streams, &streams_cell, r, c);
+	    if (streams_cell > 0)
+		if (seg_trib_nums(r, c, streams, dirs) != 1)
+		    stream_num++;
+	}
+    G_message("%d", stream_num);
+    return stream_num;
+}
+
+int seg_build_streamlines(SEGMENT *streams, SEGMENT *dirs,
+			  SEGMENT *elevation, int number_of_streams)
+{
+    int r, c, i;
+    int d, next_d;
+    int prev_r, prev_c;
+    int streams_cell, dirs_cell;
+    float elevation_prev_cell;
+    int stream_num = 1, cell_num = 0;
+    int contrib_cell;
+    STREAM *SA;
+
+    stream_num = 1;
+
+
+    stream_attributes =
+	(STREAM *) G_malloc(number_of_streams * sizeof(STREAM));
+    G_message("Finding inits...");
+    SA = stream_attributes;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+	    segment_get(streams, &streams_cell, r, c);
+	    if (streams_cell)
+		if (seg_trib_nums(r, c, streams, dirs) != 1) {	/* adding inits */
+		    if (stream_num > number_of_streams)
+			G_fatal_error(_("Error finding inits. Stream and direction maps probably do not match..."));
+
+		    SA[stream_num].stream_num = stream_num;
+		    SA[stream_num].init_r = r;
+		    SA[stream_num++].init_c = c;
+		}
+	}
+
+    for (i = 1; i < stream_num; ++i) {
+
+	r = SA[i].init_r;
+	c = SA[i].init_c;
+	segment_get(streams, &(SA[i].order), r, c);
+	//segment_get(streams,&streams_cell,r,c);
+	SA[i].number_of_cells = 0;
+	do {
+
+	    SA[i].number_of_cells++;
+	    segment_get(dirs, &dirs_cell, r, c);
+	    d = abs(dirs_cell);
+	    if (NOT_IN_REGION(d) || d == 0)
+		break;
+	    r = NR(d);
+	    c = NC(d);
+	    segment_get(streams, &streams_cell, r, c);
+	} while (streams_cell == SA[i].order);
+
+	SA[i].number_of_cells += 2;	/* add two extra points for init+ and outlet+ */
+    }
+
+    for (i = 1; i < number_of_streams; ++i) {
+
+	SA[i].points = (unsigned long int *)
+	    G_malloc((SA[i].number_of_cells) * sizeof(unsigned long int));
+	SA[i].elevation = (float *)
+	    G_malloc((SA[i].number_of_cells) * sizeof(float));
+	SA[i].distance = (double *)
+	    G_malloc((SA[i].number_of_cells) * sizeof(double));
+
+	r = SA[i].init_r;
+	c = SA[i].init_c;
+	contrib_cell =
+	    seg_find_contributing_cell(r, c, dirs, elevation);
+	prev_r = NR(contrib_cell);
+	prev_c = NC(contrib_cell);
+
+	/* add one point contributing to init to calculate parameters */
+	/* what to do if there is no contributing points? */
+	SA[i].points[0] = (contrib_cell == 0) ? -1 : INDEX(prev_r, prev_c);
+
+	segment_get(elevation, &elevation_prev_cell, prev_r, prev_c);
+	SA[i].elevation[0] = (contrib_cell == 0) ? -99999 :
+	    elevation_prev_cell;
+
+	if (contrib_cell == 0)
+	    segment_get(dirs, &d, r, c);
+	else
+	    segment_get(dirs, &d, prev_r, prev_c);
+	SA[i].distance[0] = (contrib_cell == 0) ? get_distance(r, c, d) :
+	    get_distance(prev_r, prev_c, d);
+
+	SA[i].points[1] = INDEX(r, c);
+	segment_get(elevation, &(SA[i].elevation[1]), r, c);
+	segment_get(dirs, &d, r, c);
+	SA[i].distance[1] = get_distance(r, c, d);
+
+	cell_num = 2;
+	do {
+	    segment_get(dirs, &dirs_cell, r, c);
+	    d = abs(dirs_cell);
+	    if (NOT_IN_REGION(d) || d == 0) {
+		SA[i].points[cell_num] = -1;
+		SA[i].distance[cell_num] = SA[i].distance[cell_num - 1];
+		SA[i].elevation[cell_num] =
+		    2 * SA[i].elevation[cell_num - 1] -
+		    SA[i].elevation[cell_num - 2];
+		break;
+	    }
+	    r = NR(d);
+	    c = NC(d);
+	    SA[i].points[cell_num] = INDEX(r, c);
+	    segment_get(elevation, &(SA[i].elevation[cell_num]), r, c);
+	    segment_get(dirs, &next_d, r, c);
+	    next_d = (abs(next_d) == 0) ? d : abs(next_d);
+	    SA[i].distance[cell_num] = get_distance(r, c, next_d);
+	    cell_num++;
+	    segment_get(streams, &streams_cell, r, c);
+	    if (cell_num > SA[i].number_of_cells)
+		G_fatal_error(_("To much points in stream line..."));
+	} while (streams_cell == SA[i].order);
+
+	if (SA[i].elevation[0] == -99999)
+	    SA[i].elevation[0] = 2 * SA[i].elevation[1] - SA[i].elevation[2];
+    }
+    return 0;
+}
+
+int seg_find_contributing_cell(int r, int c, SEGMENT *dirs,
+			       SEGMENT *elevation)
+{
+    int i, j = 0;
+    int next_r, next_c;
+    float elev_min = 9999;
+    int dirs_next_cell;
+    float elevation_next_cell;
+
+    for (i = 1; i < 9; ++i) {
+	if (NOT_IN_REGION(i))
+	    continue;
+	next_r = NR(i);
+	next_c = NC(i);
+	segment_get(dirs, &dirs_next_cell, next_r, next_c);
+	segment_get(elevation, &elevation_next_cell, next_r, next_c);
+	if (dirs_next_cell == DIAG(i) && elevation_next_cell < elev_min) {
+	    elev_min = elevation_next_cell;
+	    j = i;
+	}
+    }
+    return j;
+}
+
+int free_attributes(int number_of_streams)
+{
+    int i;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	G_free(SA[i].points);
+	G_free(SA[i].elevation);
+	G_free(SA[i].distance);
+    }
+    G_free(stream_attributes);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.channel/stream_write.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.channel/stream_write.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.channel/stream_write.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,505 @@
+#include "local_proto.h"
+int ram_set_null_output(DCELL **output)
+{
+
+    int r;
+
+    for (r = 0; r < nrows; ++r)
+	Rast_set_d_null_value(output[r], ncols);
+    return 0;
+}
+
+int seg_set_null_output(SEGMENT *output)
+{
+
+    int r, c;
+    double output_cell;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+	    Rast_set_d_null_value(&output_cell, 1);
+	    segment_put(output, &output_cell, r, c);
+	}
+    return 0;
+}
+
+int ram_calculate_identifiers(CELL **identifier, int number_of_streams,
+			      int downstream)
+{
+    int r, c;
+    int i, j;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    identifier[r][c] = SA[i].stream_num;
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_identifiers(SEGMENT *identifier, int number_of_streams,
+			      int downstream)
+{
+    int r, c;
+    int i, j;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    segment_put(identifier, &(SA[i].stream_num), r, c);
+	}
+    }
+    return 0;
+}
+
+
+int ram_calculate_distance(DCELL **output, int number_of_streams,
+			   int downstream)
+{
+    int r, c;
+    double cum_length;
+    int i, j;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	cum_length = 0;
+	if (!downstream)
+	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output[r][c] = cum_length;
+	    }
+	else
+	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output[r][c] = cum_length;
+	    }
+    }
+    return 0;
+}
+
+int seg_calculate_distance(SEGMENT *output, int number_of_streams,
+			   int downstream)
+{
+    int r, c;
+    double cum_length;
+    int i, j;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	cum_length = 0;
+	if (!downstream)
+	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		segment_put(output, &cum_length, r, c);
+	    }
+	else
+	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		segment_put(output, &cum_length, r, c);
+	    }
+    }
+    return 0;
+}
+
+int ram_calculate_cell(DCELL **output, int number_of_streams, int downstream)
+{
+    int r, c;
+    int i, j, k;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+
+	k = SA[i].number_of_cells - 2;
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j, --k) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    output[r][c] = downstream ? k : j;
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_cell(SEGMENT *output, int number_of_streams,
+		       int downstream)
+{
+    int r, c;
+    int i, j, k;
+    double output_cell;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+
+	k = SA[i].number_of_cells - 2;
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j, --k) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    output_cell = downstream ? k : j;
+	    segment_put(output, &output_cell, r, c);
+	}
+    }
+    return 0;
+}
+
+int ram_calculate_difference(DCELL **output, int number_of_streams,
+			     int downstream)
+{
+    int r, c;
+    int i, j;
+    double result;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    result = downstream ?
+		SA[i].elevation[j - 1] - SA[i].elevation[j] :
+		SA[i].elevation[j] - SA[i].elevation[j + 1];
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    output[r][c] = result;
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_difference(SEGMENT *output, int number_of_streams,
+			     int downstream)
+{
+    int r, c;
+    int i, j;
+    double output_cell;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    output_cell = downstream ?
+		SA[i].elevation[j - 1] - SA[i].elevation[j] :
+		SA[i].elevation[j] - SA[i].elevation[j + 1];
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    segment_put(output, &output_cell, r, c);
+	}
+    }
+    return 0;
+}
+
+int ram_calculate_drop(DCELL **output, int number_of_streams, int downstream)
+{
+    int r, c;
+    int i, j;
+    double init;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	if (!downstream) {
+	    init = SA[i].elevation[1];
+	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output[r][c] = init - SA[i].elevation[j];
+	    }
+	}
+	else {
+	    init = SA[i].elevation[SA[i].number_of_cells - 2];
+	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output[r][c] = SA[i].elevation[j] - init;
+	    }
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_drop(SEGMENT *output, int number_of_streams,
+		       int downstream)
+{
+    int r, c;
+    int i, j;
+    double init;
+    double output_cell;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	if (!downstream) {
+	    init = SA[i].elevation[1];
+	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output_cell = init - SA[i].elevation[j];
+		segment_put(output, &output_cell, r, c);
+	    }
+	}
+	else {
+	    init = SA[i].elevation[SA[i].number_of_cells - 2];
+	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output_cell = SA[i].elevation[j] - init;
+		segment_put(output, &output_cell, r, c);
+	    }
+	}
+    }
+    return 0;
+}
+
+int ram_calculate_gradient(DCELL **output, int number_of_streams,
+			   int downstream)
+{
+    int r, c;
+    int i, j;
+    double init;
+    double cum_length;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	cum_length = 0;
+	if (!downstream) {
+	    init = SA[i].elevation[0];
+	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output[r][c] = (init - SA[i].elevation[j]) / cum_length;
+	    }
+	}
+	else {
+	    init = SA[i].elevation[SA[i].number_of_cells - 1];
+	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output[r][c] = (SA[i].elevation[j] - init) / cum_length;
+	    }
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_gradient(SEGMENT *output, int number_of_streams,
+			   int downstream)
+{
+    int r, c;
+    int i, j;
+    double init;
+    double output_cell;
+    double cum_length;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	cum_length = 0;
+	if (!downstream) {
+	    init = SA[i].elevation[1];
+	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output_cell = (init - SA[i].elevation[j]) / cum_length;
+		segment_put(output, &output_cell, r, c);
+
+	    }
+	}
+	else {
+	    init = SA[i].elevation[SA[i].number_of_cells - 2];
+	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
+		cum_length += SA[i].distance[j];
+		r = (int)SA[i].points[j] / ncols;
+		c = (int)SA[i].points[j] % ncols;
+		output_cell = (SA[i].elevation[j] - init) / cum_length;
+		segment_put(output, &output_cell, r, c);
+	    }
+	}
+    }
+    return 0;
+}
+
+int ram_calculate_local_gradient(DCELL **output, int number_of_streams,
+				 int downstream)
+{
+    int r, c;
+    int i, j;
+    double elev_diff;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    elev_diff =
+		(SA[i].elevation[j] - SA[i].elevation[j + 1]) <
+		0 ? 0 : (SA[i].elevation[j] - SA[i].elevation[j + 1]);
+	    output[r][c] = elev_diff / SA[i].distance[j];
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_local_gradient(SEGMENT *output, int number_of_streams,
+				 int downstream)
+{
+    int r, c;
+    int i, j;
+    double elev_diff;
+    double output_cell;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    elev_diff =
+		(SA[i].elevation[j] - SA[i].elevation[j + 1]) <
+		0 ? 0 : (SA[i].elevation[j] - SA[i].elevation[j + 1]);
+	    output_cell = elev_diff / SA[i].distance[j];
+	    segment_put(output, &output_cell, r, c);
+	}
+    }
+    return 0;
+}
+
+
+int ram_calculate_local_distance(DCELL **output, int number_of_streams,
+				 int downstream)
+{
+    int r, c;
+    int i, j;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    output[r][c] = SA[i].distance[j];
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_local_distance(SEGMENT *output, int number_of_streams,
+				 int downstream)
+{
+    int r, c;
+    int i, j;
+    double output_cell;
+    STREAM *SA;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    output_cell = SA[i].distance[j];
+	    segment_put(output, &output_cell, r, c);
+	}
+    }
+    return 0;
+}
+
+int ram_calculate_curvature(DCELL **output, int number_of_streams,
+			    int downstream)
+{
+    int r, c;
+    int i, j;
+    STREAM *SA;
+    double first_derivative, second_derivative;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    first_derivative =
+		(SA[i].elevation[j - 1] -
+		 SA[i].elevation[j + 1]) / (SA[i].distance[j - 1] +
+					    SA[i].distance[j]);
+	    second_derivative =
+		((SA[i].elevation[j - 1] - SA[i].elevation[j]) -
+		 (SA[i].elevation[j] -
+		  SA[i].elevation[j + 1])) / (SA[i].distance[j - 1] +
+					      SA[i].distance[j]);
+	    output[r][c] =
+		first_derivative /
+		pow((1 + second_derivative * second_derivative), 1.5);
+	}
+    }
+    return 0;
+}
+
+int seg_calculate_curvature(SEGMENT *output, int number_of_streams,
+			    int downstream)
+{
+    int r, c;
+    int i, j;
+    double output_cell;
+    STREAM *SA;
+    double first_derivative, second_derivative;
+
+    SA = stream_attributes;
+
+    for (i = 1; i < number_of_streams; ++i) {
+	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
+	    r = (int)SA[i].points[j] / ncols;
+	    c = (int)SA[i].points[j] % ncols;
+	    first_derivative =
+		(SA[i].elevation[j - 1] -
+		 SA[i].elevation[j + 1]) / (SA[i].distance[j - 1] +
+					    SA[i].distance[j]);
+	    second_derivative =
+		((SA[i].elevation[j - 1] - SA[i].elevation[j]) -
+		 (SA[i].elevation[j] -
+		  SA[i].elevation[j + 1])) / (SA[i].distance[j - 1] +
+					      SA[i].distance[j]);
+	    output_cell =
+		first_derivative /
+		pow((1 + second_derivative * second_derivative), 1.5);
+	    segment_put(output, &output_cell, r, c);
+	}
+    }
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.distance/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.stream.distance
+
+LIBES = $(GISLIB) $(RASTERLIB) $(SEGMENTLIB)
+DEPENDENCIES = $(GISDEP) $(RASTERDEP) $(SEGMENTDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
+

Added: grass-addons/grass7/grass7/raster/r.stream.distance/distance_calc.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/distance_calc.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/distance_calc.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,628 @@
+#include "local_proto.h"
+static int tail, head, fifo_count;
+
+int fifo_insert(POINT point)
+{
+    if (fifo_count == fifo_max)
+	G_fatal_error("fifo queue: circular buffer too small");
+
+    fifo_points[tail++] = point;
+    if (tail > fifo_max) {
+	G_debug(1, "tail > fifo_max");
+	tail = 0;
+    }
+    fifo_count++;
+    return 0;
+}
+
+POINT fifo_return_del(void)
+{
+    if (head >= fifo_max) {
+	G_debug(1, "head >= fifo_max");
+	head = -1;
+    }
+    fifo_count--;
+
+    return fifo_points[++head];
+}
+
+
+int ram_calculate_downstream(CELL ** dirs, FCELL ** distance,
+			     FCELL ** elevation, OUTLET outlet, int outs)
+{
+
+    int r, c, i, j;
+    int next_r, next_c;
+    POINT n_cell;
+    float cur_dist = 0;
+    float tmp_dist = 0;
+    float target_elev;		/* eleavation at stream or outlet */
+    float easting, northing;
+    float cell_easting, cell_northing;
+    struct Cell_head window;
+
+    Rast_get_window(&window);
+
+    tail = 0;
+    head = -1;
+    r = outlet.r;
+    c = outlet.c;
+
+    if (elevation) {
+	target_elev = elevation[r][c];
+	elevation[r][c] = 0.;
+    }
+
+    while (tail != head) {
+	easting = window.west + (c + .5) * window.ew_res;
+	northing = window.north - (r + .5) * window.ns_res;
+
+	for (i = 1; i < 9; ++i) {
+
+	    if (NOT_IN_REGION(i))
+		continue;	/* border */
+
+	    j = DIAG(i);
+	    next_r = NR(i);
+	    next_c = NC(i);
+	    if (dirs[NR(i)][NC(i)] == j) {	/* countributing cell, reset distance and elevation */
+
+		if (outs) {	/* outlet mode */
+
+		    if (distance[NR(i)][NC(i)] == 0)
+			continue;	/* continue loop, point is not added to the queue! */
+		    else {
+			cell_northing =
+			    window.north - (next_r + .5) * window.ns_res;
+			cell_easting =
+			    window.west + (next_c + .5) * window.ew_res;
+			cur_dist =
+			    tmp_dist + G_distance(easting, northing,
+						  cell_easting,
+						  cell_northing);
+			distance[NR(i)][NC(i)] = cur_dist;
+		    }
+
+		}
+		else {		/* stream mode */
+
+		    if (distance[next_r][next_c] == 0) {
+			cur_dist = 0;
+			if (elevation)
+			    target_elev = elevation[next_r][next_c];
+		    }
+		    else {
+			cell_northing =
+			    window.north - (next_r + .5) * window.ns_res;
+			cell_easting =
+			    window.west + (next_c + .5) * window.ew_res;
+			cur_dist =
+			    tmp_dist + G_distance(easting, northing,
+						  cell_easting,
+						  cell_northing);
+			distance[NR(i)][NC(i)] = cur_dist;
+		    }
+		}		/* end stream mode */
+
+		if (elevation) {
+		    elevation[next_r][next_c] =
+			elevation[next_r][next_c] - target_elev;
+		    n_cell.target_elev = target_elev;
+		}
+
+		n_cell.r = next_r;
+		n_cell.c = next_c;
+		n_cell.cur_dist = cur_dist;
+		fifo_insert(n_cell);
+	    }
+	}			/* end for i... */
+
+	n_cell = fifo_return_del();
+	r = n_cell.r;
+	c = n_cell.c;
+	tmp_dist = n_cell.cur_dist;
+	target_elev = n_cell.target_elev;
+
+    }				/* end while */
+    return 0;
+}
+
+int seg_calculate_downstream(SEGMENT *dirs, SEGMENT * distance,
+			     SEGMENT *elevation, OUTLET outlet, int outs)
+{
+
+    int r, c, i, j;
+    int next_r, next_c;
+    POINT n_cell;
+    float cur_dist = 0;
+    float tmp_dist = 0;
+    float target_elev;		/* eleavation at stream or outlet */
+    float easting, northing;
+    float cell_easting, cell_northing;
+    CELL dirs_cell;
+    FCELL distance_cell, elevation_cell;
+    FCELL zero_cell = 0;
+    struct Cell_head window;
+
+    Rast_get_window(&window);
+
+    tail = 0;
+    head = -1;
+    r = outlet.r;
+    c = outlet.c;
+
+    if (elevation) {
+	segment_get(elevation, &target_elev, r, c);
+	segment_put(elevation, &zero_cell, r, c);
+    }
+
+    while (tail != head) {
+	easting = window.west + (c + .5) * window.ew_res;
+	northing = window.north - (r + .5) * window.ns_res;
+
+	for (i = 1; i < 9; ++i) {
+
+	    if (NOT_IN_REGION(i))
+		continue;	/* border */
+
+	    j = DIAG(i);
+	    next_r = NR(i);
+	    next_c = NC(i);
+
+	    segment_get(dirs, &dirs_cell, next_r, next_c);
+	    if (dirs_cell == j) {	/* countributing cell, reset distance and elevation */
+
+		if (outs) {	/* outlet mode */
+		    segment_get(distance, &distance_cell, next_r, next_c);
+		    if (distance_cell == 0)
+			continue;	/* continue loop, point is not added to the queue! */
+		    else {
+			cell_northing =
+			    window.north - (next_r + .5) * window.ns_res;
+			cell_easting =
+			    window.west + (next_c + .5) * window.ew_res;
+			cur_dist =
+			    tmp_dist + G_distance(easting, northing,
+						  cell_easting,
+						  cell_northing);
+			segment_put(distance, &cur_dist, next_r, next_c);
+
+		    }
+
+		}
+		else {		/* stream mode */
+		    segment_get(distance, &distance_cell, next_r, next_c);
+		    if (distance_cell == 0) {
+			cur_dist = 0;
+			if (elevation)
+			    segment_get(elevation, &target_elev, next_r,
+					next_c);
+		    }
+		    else {
+			cell_northing =
+			    window.north - (next_r + .5) * window.ns_res;
+			cell_easting =
+			    window.west + (next_c + .5) * window.ew_res;
+			cur_dist =
+			    tmp_dist + G_distance(easting, northing,
+						  cell_easting,
+						  cell_northing);
+			segment_put(distance, &cur_dist, next_r, next_c);
+		    }
+		}		/* end stream mode */
+
+		if (elevation) {
+		    segment_get(elevation, &elevation_cell, next_r, next_c);
+		    elevation_cell -= target_elev;
+		    segment_put(elevation, &elevation_cell, next_r, next_c);
+		    n_cell.target_elev = target_elev;
+		}
+
+		n_cell.r = next_r;
+		n_cell.c = next_c;
+		n_cell.cur_dist = cur_dist;
+		fifo_insert(n_cell);
+	    }
+	}			/* end for i... */
+
+	n_cell = fifo_return_del();
+	r = n_cell.r;
+	c = n_cell.c;
+	tmp_dist = n_cell.cur_dist;
+	target_elev = n_cell.target_elev;
+
+    }				/* end while */
+    return 0;
+}
+
+int ram_fill_basins(OUTLET outlet, FCELL ** distance, CELL ** dirs)
+{
+    /* fill empty spaces with zeros but leave -1 as a markers of NULL */
+    int r, c, i, j;
+    int next_r, next_c;
+    float stop, val;
+    POINT n_cell;
+
+    tail = 0;
+    head = -1;
+    r = outlet.r;
+    c = outlet.c;
+    val = 1;
+    stop = 0;
+
+    distance[r][c] = stop;
+
+    while (tail != head) {
+	for (i = 1; i < 9; ++i) {
+	    if (NOT_IN_REGION(i))
+		continue;	/* out of border */
+
+	    j = DIAG(i);
+	    next_r = NR(i);
+	    next_c = NC(i);
+
+	    if (dirs[next_r][next_c] == j) {	/* countributing cell */
+
+		distance[next_r][next_c] =
+		    (distance[next_r][next_c] == stop) ? stop : val;
+		n_cell.r = next_r;
+		n_cell.c = next_c;
+		fifo_insert(n_cell);
+	    }
+
+	}			/* end for i... */
+
+	n_cell = fifo_return_del();
+	r = n_cell.r;
+	c = n_cell.c;
+    }
+
+    return 0;
+}
+
+int seg_fill_basins(OUTLET outlet, SEGMENT * distance, SEGMENT * dirs)
+{
+    /* fill empty spaces with zeros but leave -1 as a markers of NULL */
+    int r, c, i, j;
+    int next_r, next_c;
+    float stop, val;
+    POINT n_cell;
+    CELL dirs_cell;
+    FCELL distance_cell;
+
+    tail = 0;
+    head = -1;
+    r = outlet.r;
+    c = outlet.c;
+    val = 1;
+    stop = 0;
+
+    segment_put(distance, &stop, r, c);
+
+    while (tail != head) {
+
+	for (i = 1; i < 9; ++i) {
+	    if (NOT_IN_REGION(i))
+		continue;	/* out of border */
+
+	    j = DIAG(i);
+	    next_r = NR(i);
+	    next_c = NC(i);
+
+	    segment_get(dirs, &dirs_cell, next_r, next_c);
+
+	    if (dirs_cell == j) {	/* countributing cell */
+
+		segment_get(distance, &distance_cell, next_r, next_c);
+		distance_cell = (distance_cell == stop) ? stop : val;
+		segment_put(distance, &distance_cell, next_r, next_c);
+		n_cell.r = next_r;
+		n_cell.c = next_c;
+		fifo_insert(n_cell);
+
+	    }
+	}			/* end for i... */
+
+	n_cell = fifo_return_del();
+	r = n_cell.r;
+	c = n_cell.c;
+    }
+
+    return 0;
+}
+
+int ram_calculate_upstream(FCELL ** distance, CELL ** dirs,
+			   FCELL ** elevation, FCELL ** tmp_elevation,
+			   int near)
+{
+    int r, c;
+    int next_r, next_c;
+    float easting, northing;
+    float cell_easting, cell_northing;
+    int i, j, k, d;
+    int done;
+    int counter;
+    int n_inits = 0;
+    float cur_dist;
+    POINT *d_inits;
+    float tmp_dist = 0;
+    float target_elev = 0;
+    size_t elevation_data_size;
+    struct Cell_head window;
+
+    Rast_get_window(&window);
+
+    if (elevation) {
+	elevation_data_size = Rast_cell_size(FCELL_TYPE);
+	for (r = 0; r < nrows; ++r)
+	    memcpy(tmp_elevation[r], elevation[r],
+		   ncols * elevation_data_size);
+    }
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+
+	    for (i = 1; i < 9; ++i) {
+		if (NOT_IN_REGION(i))
+		    continue;	/* out of border */
+
+		j = DIAG(i);
+		next_r = NR(i);
+		next_c = NC(i);
+		if (dirs[next_r][next_c] == j && distance[r][c] != 0) {	/* is contributing cell */
+		    distance[r][c] = -1;
+		    break;
+		}
+	    }
+	    if (distance[r][c] == 1 && dirs[r][c] > 0)
+		n_inits++;
+	    else if (dirs[r][c] > 0)
+		distance[r][c] = -1;
+	}
+
+    d_inits = (POINT *) G_malloc(n_inits * sizeof(POINT));
+
+    k = 0;
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+
+	    if (distance[r][c] == 1) {
+
+		distance[r][c] = 0;
+		if (elevation)
+		    elevation[r][c] = 0;
+
+		d = dirs[r][c];
+
+		if (dirs[NR(d)][NC(d)] < 0)
+		    continue;
+
+		d_inits[k].r = r;
+		d_inits[k].c = c;
+		d_inits[k].cur_dist = 0;
+
+
+		if (elevation)
+		    d_inits[k].target_elev = tmp_elevation[r][c];
+
+		k++;
+	    }
+	}
+
+    counter = n_inits = k;
+    //return 0; // do usunięcia
+    G_message("Calculate upstream parameters...");
+    while (n_inits > 0) {
+	k = 0;
+	G_percent((counter - n_inits), counter, 10);
+	for (i = 0; i < n_inits; ++i) {
+	    r = d_inits[i].r;
+	    c = d_inits[i].c;
+	    d = dirs[r][c];
+	    next_r = NR(d);
+	    next_c = NC(d);
+	    tmp_dist = d_inits[i].cur_dist;
+
+	    if (elevation)
+		target_elev = d_inits[i].target_elev;
+
+	    easting = window.west + (c + 0.5) * window.ew_res;
+	    northing = window.north - (r + 0.5) * window.ns_res;
+	    cell_easting = window.west + (next_c + 0.5) * window.ew_res;
+	    cell_northing = window.north - (next_r + 0.5) * window.ns_res;
+
+	    cur_dist = tmp_dist +
+		G_distance(easting, northing, cell_easting, cell_northing);
+
+	    if (near)
+		done = (distance[next_r][next_c] > cur_dist ||
+			distance[next_r][next_c] <= 0) ? 1 : 0;
+	    else
+		done = (distance[next_r][next_c] < cur_dist ||
+			distance[next_r][next_c] <= 0) ? 1 : 0;
+
+	    if (done) {
+		distance[next_r][next_c] = cur_dist;
+		if (elevation) {
+		    elevation[next_r][next_c] =
+			target_elev - tmp_elevation[next_r][next_c];
+		}
+		if (dirs[NR(d)][NC(d)] < 1)
+		    continue;
+
+		d_inits[k].r = next_r;
+		d_inits[k].c = next_c;
+		d_inits[k].cur_dist = cur_dist;
+
+		if (elevation)
+		    d_inits[k].target_elev = target_elev;
+		k++;
+	    }			/* end of if done */
+	}
+	n_inits = k;
+    }
+    G_percent((counter - n_inits), counter, 10);
+    return 0;
+}
+
+
+int seg_calculate_upstream(SEGMENT * distance, SEGMENT * dirs,
+			   SEGMENT * elevation, SEGMENT * tmp_elevation,
+			   int near)
+{
+    int r, c;
+    int next_r, next_c;
+    float easting, northing;
+    float cell_easting, cell_northing;
+    int i, j, k, d, d_next;
+    FCELL minus_one_cell = -1;
+    FCELL zero_cell = 0;
+    int done;
+    int counter;
+    int n_inits = 0;
+    float cur_dist;
+    POINT *d_inits;
+    float tmp_dist = 0;
+    float target_elev = 0;
+    CELL dirs_cell;
+    FCELL distance_cell, elevation_cell, tmp_elevation_cell;
+    size_t elevation_data_size;
+    struct Cell_head window;
+
+    Rast_get_window(&window);
+
+    if (elevation) {
+	elevation_data_size = Rast_cell_size(FCELL_TYPE);
+	for (r = 0; r < nrows; ++r)
+	    for (c = 0; c < ncols; ++c) {
+		segment_get(elevation, &elevation_cell, r, c);
+		segment_put(tmp_elevation, &elevation_cell, r, c);
+	    }
+    }
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+
+	    segment_get(distance, &distance_cell, r, c);
+
+	    for (i = 1; i < 9; ++i) {
+		if (NOT_IN_REGION(i))
+		    continue;	/* out of border */
+
+		j = DIAG(i);
+		next_r = NR(i);
+		next_c = NC(i);
+
+		segment_get(dirs, &dirs_cell, next_r, next_c);
+
+		if (dirs_cell == j && distance_cell != 0) {	/* is contributing cell */
+		    segment_put(distance, &minus_one_cell, r, c);
+		    break;
+		}
+	    }			/* end for i */
+
+	    segment_get(distance, &distance_cell, r, c);
+	    segment_get(dirs, &dirs_cell, r, c);
+	    if (distance_cell == 1) {
+		if (distance_cell == 1 && dirs_cell > 0)
+		    n_inits++;
+		else if (dirs_cell > 0)
+		    segment_put(distance, &minus_one_cell, r, c);
+	    }
+
+	}
+
+    d_inits = (POINT *) G_malloc(n_inits * sizeof(POINT));
+
+    k = 0;
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+
+	    segment_get(distance, &distance_cell, r, c);
+	    if (distance_cell == 1) {
+
+		segment_put(distance, &zero_cell, r, c);
+		if (elevation)
+		    segment_put(elevation, &zero_cell, r, c);
+
+		segment_get(dirs, &d, r, c);
+		segment_get(dirs, &d_next, NR(d), NR(d));
+
+		if (d_next < 0)
+		    continue;
+
+		d_inits[k].r = r;
+		d_inits[k].c = c;
+		d_inits[k].cur_dist = 0;
+
+		if (elevation)
+		    segment_get(tmp_elevation, &(d_inits[k].target_elev), r,
+				c);
+		k++;
+	    }
+	}
+
+    counter = n_inits = k;
+
+    G_message("Calculate upstream parameters...");
+    while (n_inits > 0) {
+	k = 0;
+	G_percent((counter - n_inits), counter, 10);
+
+	for (i = 0; i < n_inits; ++i) {
+	    r = d_inits[i].r;
+	    c = d_inits[i].c;
+
+	    segment_get(dirs, &d, r, c);
+	    next_r = NR(d);
+	    next_c = NC(d);
+	    tmp_dist = d_inits[i].cur_dist;
+
+	    if (elevation)
+		target_elev = d_inits[i].target_elev;
+
+	    easting = window.west + (c + 0.5) * window.ew_res;
+	    northing = window.north - (r + 0.5) * window.ns_res;
+	    cell_easting = window.west + (next_c + 0.5) * window.ew_res;
+	    cell_northing = window.north - (next_r + 0.5) * window.ns_res;
+
+	    cur_dist = tmp_dist +
+		G_distance(easting, northing, cell_easting, cell_northing);
+
+	    segment_get(distance, &distance_cell, next_r, next_c);
+
+	    if (near)
+		done = (distance_cell > cur_dist ||
+			distance_cell <= 0) ? 1 : 0;
+	    else
+		done = (distance_cell < cur_dist ||
+			distance_cell <= 0) ? 1 : 0;
+
+	    if (done) {
+		segment_put(distance, &cur_dist, next_r, next_c);
+		if (elevation) {
+		    segment_get(tmp_elevation, &tmp_elevation_cell, next_r,
+				next_c);
+		    tmp_elevation_cell = target_elev - tmp_elevation_cell;
+		    segment_put(elevation, &tmp_elevation_cell, next_r,
+				next_c);
+		}
+
+		segment_get(dirs, &dirs_cell, NR(d), NC(d));
+		if (dirs_cell < 1)
+		    continue;
+
+		d_inits[k].r = next_r;
+		d_inits[k].c = next_c;
+		d_inits[k].cur_dist = cur_dist;
+
+		if (elevation)
+		    d_inits[k].target_elev = target_elev;
+		k++;
+	    }			/* end of if done */
+	}
+	n_inits = k;
+    }
+    G_percent((counter - n_inits), counter, 10);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.distance/distance_init.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/distance_init.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/distance_init.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,208 @@
+#include "local_proto.h"
+
+int ram_find_outlets(CELL ** streams, int number_of_streams, CELL ** dirs,
+		     int subs, int outs)
+{
+    int d;			/* d: direction */
+    int r, c;
+    int next_stream = -1, cur_stream;
+    int out_max = ncols + nrows;
+    int outlets_num;
+
+    G_message(_("Finding nodes..."));
+    outlets = (OUTLET *) G_malloc((out_max) * sizeof(OUTLET));
+
+    outlets_num = 0;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c)
+	    if (streams[r][c] > 0) {
+		if (outlets_num > (out_max - 1)) {
+		    if (outlets_num > 4 * (out_max - 1))
+			G_fatal_error
+			    ("Stream and direction maps probably do not match");
+		    out_max *= 4;
+		    outlets =
+			(OUTLET *) G_realloc(outlets,
+					     (out_max) * sizeof(OUTLET));
+		}
+
+		d = abs(dirs[r][c]);	/* r.watershed */
+
+		if (NOT_IN_REGION(d)) {
+		    next_stream = -1;
+		}
+		else {
+		    next_stream = streams[NR(d)][NC(d)];
+		    if (next_stream < 1)
+			next_stream = -1;
+		}
+
+		if (d == 0)
+		    next_stream = -1;
+
+		cur_stream = streams[r][c];
+
+		if (subs && outs) {	/* in stream mode subs is ignored */
+		    if (cur_stream != next_stream) {	/* is outlet or node! */
+			outlets[outlets_num].r = r;
+			outlets[outlets_num++].c = c;
+		    }
+		}
+		else {
+		    if (next_stream < 0) {	/* is outlet! */
+			outlets[outlets_num].r = r;
+			outlets[outlets_num++].c = c;
+		    }
+		}		/* end lasts */
+	    }			/* end if streams */
+
+    return outlets_num;
+}
+
+
+int seg_find_outlets(SEGMENT * streams, int number_of_streams, SEGMENT * dirs,
+		     int subs, int outs)
+{
+    int d;			/* d: direction */
+    int r, c;
+    int next_stream = -1;
+    int out_max = ncols + nrows;
+    int outlets_num;
+    CELL streams_cell;
+    CELL dirs_cell;
+
+    G_message(_("Finding nodes..."));
+    outlets = (OUTLET *) G_malloc((out_max) * sizeof(OUTLET));
+
+    outlets_num = 0;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+	    segment_get(streams, &streams_cell, r, c);
+
+	    if (streams_cell > 0) {
+		if (outlets_num > (out_max - 1)) {
+		    if (outlets_num > 4 * (out_max - 1))
+			G_fatal_error
+			    ("Stream and direction maps probably do not match");
+		    out_max *= 4;
+		    outlets =
+			(OUTLET *) G_realloc(outlets,
+					     (out_max) * sizeof(OUTLET));
+		}
+
+		segment_get(dirs, &dirs_cell, r, c);
+		d = abs(dirs_cell);	/* r.watershed */
+
+		if (NOT_IN_REGION(d)) {
+		    next_stream = -1;
+		}
+		else {
+		    segment_get(streams, &next_stream, NR(d), NC(d));
+		    if (next_stream < 1)
+			next_stream = -1;
+		}
+
+		if (d == 0)
+		    next_stream = -1;
+
+		if (subs && outs) {	/* in stream mode subs is ignored */
+		    if (streams_cell != next_stream) {	/* is outlet or node! */
+			outlets[outlets_num].r = r;
+			outlets[outlets_num++].c = c;
+		    }
+		}
+		else {
+		    if (next_stream < 0) {	/* is outlet! */
+			outlets[outlets_num].r = r;
+			outlets[outlets_num++].c = c;
+		    }
+		}		/* end lasts */
+	    }			/* end if streams */
+	}			/* end for c */
+    return outlets_num;
+}
+
+int ram_init_distance(CELL ** streams, FCELL ** distance, int outlets_num,
+		      int outs)
+{
+    int r, c, i;
+    size_t data_size;
+
+    data_size = Rast_cell_size(FCELL_TYPE);
+
+    if (!outs) {		/* stream mode */
+	for (r = 0; r < nrows; ++r)
+	    for (c = 0; c < ncols; ++c)
+		distance[r][c] = (streams[r][c]) ? 0 : -1;
+    }
+    else {			/* outlets mode */
+	for (r = 0; r < nrows; ++r)
+	    for (c = 0; c < ncols; ++c)
+		distance[r][c] = -1;
+
+	for (i = 0; i < outlets_num; ++i)
+	    distance[outlets[i].r][outlets[i].c] = 0;
+    }
+
+    return 0;
+}
+
+int seg_init_distance(SEGMENT * streams, SEGMENT * distance, int outlets_num,
+		      int outs)
+{
+    int r, c, i;
+    CELL streams_cell;
+    FCELL distance_cell;
+    FCELL minus_one_cell = -1;
+    FCELL zero_cell = 0;
+
+    if (!outs) {		/* stream mode */
+	for (r = 0; r < nrows; ++r)
+	    for (c = 0; c < ncols; ++c) {
+		segment_get(streams, &streams_cell, r, c);
+		distance_cell = (streams_cell) ? 0 : -1;
+		segment_put(distance, &distance_cell, r, c);
+	    }
+    }
+    else {			/* outlets mode */
+	for (r = 0; r < nrows; ++r)
+	    for (c = 0; c < ncols; ++c)
+		segment_put(distance, &minus_one_cell, r, c);
+
+	for (i = 0; i < outlets_num; ++i)
+	    segment_put(distance, &zero_cell, outlets[i].r, outlets[i].c);
+    }
+    return 0;
+}
+
+int ram_prep_null_elevation(FCELL ** distance, FCELL ** elevation)
+{
+
+    int r, c;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c)
+	    if (distance[r][c] == -1) {
+		elevation[r][c] = -1;
+	    }
+
+    return 0;
+}
+
+
+int seg_prep_null_elevation(SEGMENT * distance, SEGMENT * elevation)
+{
+    int r, c;
+    FCELL distance_cell;
+
+    for (r = 0; r < nrows; ++r)
+	for (c = 0; c < ncols; ++c) {
+	    segment_get(distance, &distance_cell, r, c);
+	    if (distance_cell == -1)
+		segment_put(elevation, &distance_cell, r, c);
+	}
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.distance/io.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/io.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/io.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,564 @@
+#include "io.h"
+/* all in ram functions section */
+
+int ram_create_map(MAP * map, RASTER_MAP_TYPE data_type)
+{
+
+    /* 
+     * allocates 0 filled nrows*ncols map of type void;
+     * map parameters are stored in structure;
+     * map: map to be created;
+     * map type to be created must be CELL, FCELL, DCELL;
+     * */
+
+    int r;
+
+    if (data_type < 0 || data_type > 2)
+	G_fatal_error(_("ram_creat: Cannot create map of unrecognised type"));
+
+    map->data_type = data_type;
+    map->map_name = NULL;
+    map->nrows = Rast_window_rows();
+    map->ncols = Rast_window_cols();
+    map->data_size = Rast_cell_size(data_type);
+
+    /* preparing internal map */
+    switch (map->data_type) {
+    case CELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(CELL *));
+	break;
+
+    case FCELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(FCELL *));
+	break;
+
+    case DCELL_TYPE:
+	map->map = G_calloc(map->nrows, sizeof(DCELL *));
+	break;
+    }
+
+    for (r = 0; r < map->nrows; ++r)
+	(map->map)[r] = G_calloc(map->ncols, map->data_size);
+
+    return 0;
+}
+
+int ram_read_map(MAP * map, char *input_map_name, int check_res,
+		 RASTER_MAP_TYPE check_data_type)
+{
+    /*
+     * Funciton read external map and put it in MAP structure (created with create_map)
+     * map: map to be read can be of any data type, read map is converted to target map if neccesary.
+     * input_map_name: name of the map to be read;
+     * map pointer to map stucture (created with create_map);
+     * check_res: [1]: check res correspondence between region and map [0 no check];
+     * check_data_type [CELL, FCELL, DCELL] check if reading map is of particular type, [-1] no check;
+     */
+
+    int r, c;
+    char *mapset;
+    struct Cell_head cellhd, this_window;
+    char *maptypes[] = { "CELL", "FCELL", "DCELL" };
+    int input_map_fd;
+    RASTER_MAP_TYPE input_data_type;
+    size_t input_data_size;
+    void *input_buffer = NULL;
+    void *input_pointer;
+
+    /* checking if map exist */
+    mapset = (char *)G_find_raster2(input_map_name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), input_map_name);
+
+    /* checking if region and input are the same */
+    G_get_window(&this_window);
+    Rast_get_cellhd(input_map_name, mapset, &cellhd);
+    if (check_res)
+	if (this_window.ew_res != cellhd.ew_res ||
+	    this_window.ns_res != cellhd.ns_res)
+	    G_fatal_error(_("Region resolution and map %s resolution differs. \
+		Run g.region rast=%s to set proper region resolution"),
+			  input_map_name, input_map_name);
+
+    /* checking if input map is of required type */
+    if (check_data_type != map->data_type)
+	G_debug(1,
+		"ram_open:required map type and internal map type differs: conversion forced!");
+    input_data_type = Rast_map_type(input_map_name, mapset);
+    if (check_data_type != -1)
+	if (input_data_type != check_data_type)
+	    G_fatal_error(_("<%s> is not of type %s"),
+			  input_map_name, maptypes[check_data_type]);
+
+    input_map_fd = Rast_open_old(input_map_name, mapset);
+    input_data_size = Rast_cell_size(input_data_type);
+
+    {				/* reading range */
+	struct Range map_range;
+	struct FPRange map_fp_range;
+	int min, max;
+
+	if (input_data_type == CELL_TYPE) {
+	    Rast_init_range(&map_range);
+	    Rast_read_range(input_map_name, mapset, &map_range);
+	    Rast_get_range_min_max(&map_range, &min, &max);
+	    map->min = (double)min;
+	    map->max = (double)max;
+	}
+	else {
+	    Rast_init_fp_range(&map_fp_range);
+	    Rast_read_fp_range(input_map_name, mapset, &map_fp_range);
+	    Rast_get_fp_range_min_max(&map_fp_range, &(map->min),
+				      &(map->max));
+	}
+    }
+    /* end opening and checking */
+
+    input_buffer = Rast_allocate_buf(input_data_type);
+
+    /* start reading */
+    G_message(_("Reading map <%s>"), input_map_name);
+
+    for (r = 0; r < map->nrows; ++r) {
+	G_percent(r, map->nrows, 2);
+
+	Rast_get_row(input_map_fd, input_buffer, r, input_data_type);
+	input_pointer = input_buffer;
+
+	for (c = 0; c < map->ncols; ++c)
+	    if (!Rast_is_null_value
+		(input_pointer + c * input_data_size, input_data_type))
+		switch (map->data_type) {
+		case CELL_TYPE:
+		    ((CELL **) map->map)[r][c] =
+			Rast_get_c_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case FCELL_TYPE:
+		    ((FCELL **) map->map)[r][c] =
+			Rast_get_f_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case DCELL_TYPE:
+		    ((DCELL **) map->map)[r][c] =
+			Rast_get_d_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		default:
+		    G_fatal_error(_("ram_open:Wrong internal data type"));
+		    break;
+		}
+    }				/*end for r */
+
+    G_free(input_buffer);
+    G_percent(r, map->nrows, 2);
+    Rast_close(input_map_fd);
+    return 0;
+}				/* end create floating point map */
+
+int ram_reset_map(MAP * map, int value)
+{
+    /*
+     * set all cells in the map to value
+     */
+    int r;
+
+    for (r = 0; r < map->nrows; ++r)
+	memset((map->map)[r], value, map->ncols * map->data_size);
+    return 0;
+}
+
+int ram_write_map(MAP * map, char *output_map_name,
+		  RASTER_MAP_TYPE output_data_type, int convert_to_null,
+		  double value)
+{
+    /* 
+     * write map to disk with output_map_name and output_data_type [CELL, FCELL, DCELL];
+     * if output_data_type = -1 than internal map type is used for output;
+     * if output map != -1 and types differ data_type, conversion is forced
+     * convert to null: check if convert to null a particular value in dataset;
+     */
+
+    int r, c;
+    int output_fd = 0;
+    struct History history;
+    void *row;
+
+    /* check for output format */
+    if (output_data_type == -1)
+	output_data_type = map->data_type;
+
+    if (output_data_type != map->data_type)
+	G_debug(1,
+		"ram_write:required map type and internal map type differs: conversion forced!");
+
+    G_message(_("Writing map <%s>"), output_map_name);
+    output_fd = Rast_open_new(output_map_name, output_data_type);
+
+    /* writing */
+    for (r = 0; r < map->nrows; ++r) {
+	G_percent(r, map->nrows, 2);
+
+	if (convert_to_null) {
+	    row = map->map[r];
+	    switch (map->data_type) {
+	    case CELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((CELL *) row)[c] == (CELL) value)
+			Rast_set_c_null_value(row + c * (map->data_size), 1);
+		break;
+	    case FCELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((FCELL *) row)[c] == (FCELL) value)
+			Rast_set_f_null_value(row + c * (map->data_size), 1);
+		break;
+	    case DCELL_TYPE:
+		for (c = 0; c < map->ncols; ++c)
+		    if (((DCELL *) row)[c] == (DCELL) value)
+			Rast_set_d_null_value(row + c * (map->data_size), 1);
+		break;
+	    default:
+		G_debug(1, "ram_null:Cannot convert to null at: %d %d", r, c);
+	    }
+	}
+
+	Rast_put_row(output_fd, (map->map)[r], output_data_type);
+    }
+    G_percent(r, map->nrows, 2);
+    Rast_close(output_fd);
+    Rast_short_history(output_map_name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(output_map_name, &history);
+    G_message(_("<%s> Done"), output_map_name);
+    return 0;
+}
+
+int ram_release_map(MAP *map)
+{
+    /* 
+     * free memory allocated for map, set pointer to null;
+     */
+    int r;
+
+    for (r = 0; r < map->nrows; ++r)
+	G_free((map->map)[r]);
+    G_free(map->map);
+    map = NULL;
+    return 0;
+}
+
+
+/* memory swap functions section */
+
+
+int seg_create_map(SEG * seg, int srows, int scols, int number_of_segs,
+		   RASTER_MAP_TYPE data_type)
+{
+    /* create segment  and returns pointer to it;
+     * seg must be declared first;
+     * parameters are stored in structure;
+     * seg: segment to be created;
+     * srows, scols segment size
+     * number of segs max number of segs stored in memory
+     * data_type to be created must be CELL, FCELL, DCELL;
+     */
+
+    char *filename;
+    int fd;
+    int local_number_of_segs;
+
+    seg->fd = -1;
+    seg->filename = NULL;
+    seg->map_name = NULL;
+    seg->mapset = NULL;
+    seg->data_type = data_type;
+    seg->nrows = Rast_window_rows();
+    seg->ncols = Rast_window_cols();
+
+    local_number_of_segs =
+	(seg->nrows / srows + 1) * (seg->ncols / scols + 1);
+    number_of_segs =
+	(number_of_segs >
+	 local_number_of_segs) ? local_number_of_segs : number_of_segs;
+
+    G_debug(3, "seg_creat:number of segments %d", number_of_segs);
+
+    switch (seg->data_type) {
+    case CELL_TYPE:
+	seg->data_size = sizeof(CELL);
+	break;
+    case FCELL_TYPE:
+	seg->data_size = sizeof(FCELL);
+	break;
+    case DCELL_TYPE:
+	seg->data_size = sizeof(DCELL);
+	break;
+    default:
+	G_fatal_error(_("seg_create: unrecognisabe data type"));
+    }
+
+    filename = G_tempfile();
+    fd = creat(filename, 0666);
+
+    if (0 >
+	segment_format(fd, seg->nrows, seg->ncols, srows, scols,
+		       seg->data_size)) {
+	close(fd);
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot format segment"));
+    }
+
+    close(fd);
+    if (0 > (fd = open(filename, 2))) {
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot re-open file"));
+    }
+
+    if (0 > (fd = segment_init(&(seg->seg), fd, number_of_segs))) {
+	unlink(filename);
+	G_fatal_error(_("seg_create: cannot init segment file or out of memory"));
+    }
+
+    seg->filename = G_store(filename);
+    seg->fd = fd;
+    return 0;
+}
+
+int seg_read_map(SEG * seg, char *input_map_name, int check_res,
+		 RASTER_MAP_TYPE check_data_type)
+{
+
+    /*
+     * Funciton read external map and put it in SEG structure (created with seg_create_map)
+     * map to be read can be of any data type, read map is converted if neccesary.
+     * input_map_name: name of the map to be read;
+     * seg: pointer to map stucture (created with create_map);
+     * check_res: [1]: check res correspondence between region and map [0 no check];
+     * check_data_type [CELL, FCELL, DCELL] check if reading map is of particular type, [-1] no check;
+     */
+
+    int input_fd;
+    int r, c;
+    char *mapset;
+    struct Cell_head cellhd, this_window;
+    char *maptypes[] = { "CELL", "FCELL", "DCELL" };
+    RASTER_MAP_TYPE input_data_type;
+    size_t input_data_size;
+    void *input_buffer = NULL;
+    void *target_buffer = NULL;
+    void *input_pointer = NULL;
+
+    /* checking if map exist */
+    mapset = (char *)G_find_raster2(input_map_name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("seg_read:Raster map <%s> not found"),
+		      input_map_name);
+    seg->mapset = mapset;
+
+    /* checking if region and input are the same */
+    G_get_window(&this_window);
+    Rast_get_cellhd(input_map_name, mapset, &cellhd);
+
+    /* check resolution equal anyinteger check;  equal 0 no check */
+    if (check_res)
+	if (this_window.ew_res != cellhd.ew_res ||
+	    this_window.ns_res != cellhd.ns_res)
+	    G_fatal_error(_("Region resolution and map %s resolution differs. \
+		Run g.region rast=%s to set proper region resolution"),
+			  input_map_name, input_map_name);
+
+    if (check_data_type != seg->data_type)
+	G_debug(1,
+		"ram_open:required map type and internal map type differs: conversion forced!");
+    input_data_type = Rast_map_type(input_map_name, mapset);
+    if (check_data_type != -1)
+	if (input_data_type != check_data_type)
+	    G_fatal_error(_("<%s> is not of type %s"),
+			  input_map_name, maptypes[check_data_type]);
+
+    input_fd = Rast_open_old(input_map_name, mapset);
+    input_data_size = Rast_cell_size(input_data_type);
+
+    {				/* reading range */
+	struct Range map_range;
+	struct FPRange map_fp_range;
+	int min, max;
+
+	if (input_data_type == CELL_TYPE) {
+	    Rast_init_range(&map_range);
+	    Rast_read_range(input_map_name, mapset, &map_range);
+	    Rast_get_range_min_max(&map_range, &min, &max);
+	    seg->min = (double)min;
+	    seg->max = (double)max;
+	}
+	else {
+	    Rast_init_fp_range(&map_fp_range);
+	    Rast_read_fp_range(input_map_name, mapset, &map_fp_range);
+	    Rast_get_fp_range_min_max(&map_fp_range, &(seg->min),
+				      &(seg->max));
+	}
+    }
+
+    /* end opening and checking */
+
+    G_message(_("Reading map <%s>"), input_map_name);
+    input_buffer = Rast_allocate_buf(input_data_type);
+
+    target_buffer = Rast_allocate_buf(seg->data_type);
+
+    for (r = 0; r < seg->nrows; ++r) {
+	G_percent(r, seg->nrows, 2);
+	Rast_get_row(input_fd, input_buffer, r, input_data_type);
+	input_pointer = input_buffer;
+	memset(target_buffer, 0, seg->ncols * seg->data_size);
+
+	for (c = 0; c < seg->ncols; ++c)
+	    if (!Rast_is_null_value
+		(input_pointer + c * input_data_size, input_data_type)) {
+		switch (seg->data_type) {
+		case CELL_TYPE:
+		    ((CELL *) target_buffer)[c] =
+			Rast_get_c_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case FCELL_TYPE:
+		    ((FCELL *) target_buffer)[c] =
+			Rast_get_f_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		case DCELL_TYPE:
+		    ((DCELL *) target_buffer)[c] =
+			Rast_get_d_value(input_pointer + c * input_data_size,
+					 input_data_type);
+		    break;
+		default:
+		    G_fatal_error(_("Wrong internal data type"));
+		    break;
+		}
+	    }
+
+	if (0 > segment_put_row(&(seg->seg), target_buffer, r)) {
+	    G_free(input_buffer);
+	    G_free(target_buffer);
+	    Rast_close(input_fd);
+	    G_fatal_error(_("seg_read: Cannot segment put row %d for map %s"),
+			  r, input_map_name);
+	}
+    }				/* end for row */
+
+    G_percent(r, seg->nrows, 2);
+    Rast_close(input_fd);
+    G_free(input_buffer);
+    G_free(target_buffer);
+
+    seg->map_name = G_store(input_map_name);
+    seg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int seg_reset_map(SEG * seg, int value)
+{
+    /*
+     * set all cells in the map to value
+     */
+    int r, c;
+
+    for (r = 0; r < seg->nrows; ++r)
+	for (c = 0; c < seg->ncols; ++c)
+	    segment_put(&(seg->seg), &value, r, c);
+
+    return 0;
+}
+
+int seg_write_map(SEG * seg, char *output_map_name,
+		  RASTER_MAP_TYPE output_data_type, int convert_to_null,
+		  double value)
+{
+    /* 
+     * write seg to disk with output_map_name and output_data_type [CELL, FCELL, DCELL];
+     * if output_data_type = -1 than internal map type is used for output;
+     * if output map != -1 and types differ data_type, conversion is forced
+     * convert to null: check if convert to null a particular value in dataset;
+     */
+    int output_fd;
+    int r, c;
+    void *output_buffer;
+    void *row;
+    struct History history;
+
+    /* check for output format */
+    if (output_data_type == -1)
+	output_data_type = seg->data_type;
+
+    if (output_data_type != seg->data_type)
+	G_debug(1,
+		"ram_write:required map type and internal map type differs: conversion forced!");
+
+    G_message(_("Writing map <%s>"), output_map_name);
+    output_fd = Rast_open_new(output_map_name, output_data_type);
+    output_buffer = Rast_allocate_buf(output_data_type);
+    segment_flush(&(seg->seg));
+
+    /* writing */
+    for (r = 0; r < seg->nrows; ++r) {
+
+	G_percent(r, seg->nrows, 2);
+	if (0 > segment_get_row(&(seg->seg), output_buffer, r))
+	    G_warning(_("seg_write: Cannot segment read row %d for map %s"),
+		      r, output_map_name);
+
+	if (convert_to_null) {
+
+	    row = output_buffer;
+	    switch (seg->data_type) {
+	    case CELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((CELL *) output_buffer)[c] == (CELL) value)
+			Rast_set_c_null_value(row + c * (seg->data_size), 1);
+		break;
+	    case FCELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((FCELL *) output_buffer)[c] == (FCELL) value)
+			Rast_set_f_null_value(row + c * (seg->data_size), 1);
+		break;
+	    case DCELL_TYPE:
+		for (c = 0; c < seg->ncols; ++c)
+		    if (((DCELL *) output_buffer)[c] == (DCELL) value)
+			Rast_set_d_null_value(row + c * (seg->data_size), 1);
+		break;
+	    default:
+		G_warning(_("ram_null:Cannot convert to null at: %d %d"), r,
+			  c);
+	    }
+	}
+	Rast_put_row(output_fd, output_buffer, output_data_type);
+    }
+
+    G_percent(r, seg->nrows, 2);
+    G_free(output_buffer);
+    Rast_close(output_fd);
+    Rast_short_history(output_map_name, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(output_map_name, &history);
+    G_message(_("%s Done"), output_map_name);
+
+    return 0;
+}
+
+int seg_release_map(SEG * seg)
+{
+    /* 
+     * release segment close files, set pointers to null;
+     */
+    segment_release(&(seg->seg));
+    close(seg->fd);
+    unlink(seg->filename);
+
+    if (seg->map_name)
+	G_free(seg->map_name);
+    if (seg->mapset)
+	G_free(seg->mapset);
+
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.distance/io.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/io.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/io.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/segment.h>
+
+#define NOT_IN_REGION(x) (r + nextr[(x)] < 0 || r + nextr[(x)] > (nrows - 1) || \
+                          c + nextc[(x)] < 0 || c + nextc[(x)] > (ncols - 1))
+#define NR(x) (r + nextr[(x)])
+#define NC(x) (c + nextc[(x)])
+#define INDEX(r,c) ((r) * ncols + (c))
+#define DIAG(x) (((x) + 4) > 8 ? ((x) - 4) : ((x) + 4))
+
+#define SROWS 256
+#define SCOLS 256
+
+typedef struct {
+	void **map; /* matrix of data */
+	double min, max; /* data range : may requre casting */
+	int nrows, ncols;
+	char *map_name; /* map name, unused */
+	RASTER_MAP_TYPE data_type; /* type of data */
+	size_t data_size; /* type of data */
+} MAP;
+
+typedef struct {
+	SEGMENT seg;		/* segmented data store */
+	int fd;					/* segment temporary file name descriptor */
+	char *filename; /* segment temporary file name */
+	char *map_name; /* map name converted to segment */
+	char *mapset;
+	int nrows, ncols; /* store nrows and rcols */
+	RASTER_MAP_TYPE data_type; /* data type of the map */
+	size_t data_size; /* size of cell returned by sizeof */
+	double min, max; /* data range */
+} SEG;
+
+
+/* all in ram functions */
+int ram_create_map(MAP *, RASTER_MAP_TYPE);
+int ram_read_map(MAP *, char *, int, RASTER_MAP_TYPE);
+int ram_reset_map(MAP *, int);
+int ram_write_map(MAP *, char *, RASTER_MAP_TYPE, int, double);
+int ram_release_map(MAP *);
+int ram_destory_map(MAP *);
+
+/* memory swap functions */
+int seg_create_map(SEG *, int, int, int, RASTER_MAP_TYPE);
+int seg_read_map(SEG *, char *, int, RASTER_MAP_TYPE);
+int seg_reset_map (SEG *, int);
+int seg_write_map(SEG *, char *, RASTER_MAP_TYPE, int, double);
+int seg_release_map(SEG *);
+

Added: grass-addons/grass7/grass7/raster/r.stream.distance/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,22 @@
+#include "io.h"
+#include "local_vars.h"
+
+/* inits */
+int ram_find_outlets(CELL **streams, int number_of_streams, CELL **dirs, int subs, int outs);
+int ram_init_distance(CELL **streams, FCELL **distance, int outlets_num, int outs);
+int ram_prep_null_elevation(FCELL **distance, FCELL **elevation);
+
+int seg_find_outlets(SEGMENT *streams, int number_of_streams, SEGMENT *dirs, int subs, int outs);
+int seg_prep_null_elevation(SEGMENT *distance, SEGMENT *elevation);
+int seg_init_distance(SEGMENT *streams, SEGMENT *distance, int outlets_num, int outs);
+
+/* calculate */
+int ram_calculate_downstream(CELL **dirs, FCELL **distance, FCELL **elevation, OUTLET outlet, int outs);
+int ram_fill_basins(OUTLET outlet, FCELL **distance, CELL **dirs);
+int ram_calculate_upstream(FCELL **distance, CELL **dirs, FCELL **elevation, FCELL **tmp_elevation, int near);
+
+int seg_calculate_downstream (SEGMENT *dirs, SEGMENT *distance, SEGMENT *elevation, OUTLET outlet, int outs);
+int seg_fill_basins(OUTLET outlet, SEGMENT *distance, SEGMENT *dirs);
+int seg_calculate_upstream(SEGMENT *distance, SEGMENT *dirs, SEGMENT *elevation, SEGMENT *tmp_elevation, int near);
+
+

Added: grass-addons/grass7/grass7/raster/r.stream.distance/local_vars.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/local_vars.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/local_vars.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <grass/glocale.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+
+#ifdef MAIN
+#  define GLOBAL
+#else
+#  define GLOBAL extern
+#endif
+
+#define SQRT2 1.414214
+#define UPSTREAM 0
+#define DOWNSTREAM 1
+
+typedef struct {
+	int r,c;
+} OUTLET;
+
+typedef struct {
+	int r,c;
+  float cur_dist;
+  float target_elev;
+} POINT;
+
+GLOBAL int nextr[9];
+GLOBAL int nextc[9];
+
+GLOBAL OUTLET* outlets;
+GLOBAL int nrows, ncols;
+GLOBAL int fifo_max;
+GLOBAL POINT* fifo_points;
+GLOBAL int accum;
+
+
+
+
+
+

Added: grass-addons/grass7/grass7/raster/r.stream.distance/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,316 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.stream.distance
+ * AUTHOR(S):    Jarek Jasiewicz jarekj amu.edu.pl
+ *               
+ * PURPOSE:      Calculate distance and elevation over the streams and outlets 
+ *               according user's input data. The elevation and distance is calculated
+ *               along watercourses
+ *               It uses any stream map  and r.watershed or .stream.extreact direction map.
+ *               Stram input map shall contains streams or points outlets with or
+ *               without unique categories
+ *
+ * COPYRIGHT:    (C) 2002,2009 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *   	    	 	  License (>=v2). Read the file COPYING that comes with GRASS
+ *   	    	 	  for details.
+ *
+ *****************************************************************************/
+#define MAIN
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int nextr[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+int nextc[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+
+int process_cat(char **cat_list);
+int main(int argc, char *argv[])
+{
+
+    struct GModule *module;
+    struct Option *in_dir_opt,
+	*in_stm_opt,
+	*in_elev_opt,
+	*in_method_opt, *opt_swapsize, *out_dist_opt, *out_diff_opt;
+    struct Flag *flag_outs, *flag_sub, *flag_near, *flag_segmentation;
+    char *method_name[] = { "UPSTREAM", "DOWNSTREAM" };
+    int method;
+    int number_of_segs;
+    int outlets_num;
+    int number_of_streams;
+    int outs, subs, near, segmentation;	/*flags */
+    int j;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->description =
+	_("Calculate distance to and alavation above streams \
+    and outlets according user' input. It can work in stream mode where target are streams and outlets mode \
+    where targets are outlets");
+
+    G_add_keyword("watercourse distance");
+    G_add_keyword("relative elevation");
+
+    in_stm_opt = G_define_standard_option(G_OPT_R_INPUT);
+    in_stm_opt->key = "stream";
+    in_stm_opt->description = "Name of streams (outlets) mask input map";
+
+    in_dir_opt = G_define_standard_option(G_OPT_R_INPUT);
+    in_dir_opt->key = "dirs";
+    in_dir_opt->description = "Name of flow direction input map";
+
+    in_elev_opt = G_define_standard_option(G_OPT_R_INPUT);
+    in_elev_opt->key = "elevation";
+    in_elev_opt->required = NO;
+    in_elev_opt->description = "Name of elevation map";
+
+    in_method_opt = G_define_option();
+    in_method_opt->key = "method";
+    in_method_opt->description = "Calculation method";
+    in_method_opt->type = TYPE_STRING;
+    in_method_opt->required = YES;
+    in_method_opt->options = "upstream,downstream";
+    in_method_opt->answer = "downstream";
+
+    opt_swapsize = G_define_option();
+    opt_swapsize->key = "memory";
+    opt_swapsize->type = TYPE_INTEGER;
+    opt_swapsize->answer = "300";
+    opt_swapsize->description = _("Max memory used in memory swap mode (MB)");
+    opt_swapsize->guisection = _("Optional");
+
+    out_dist_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_dist_opt->key = "distance";
+    out_dist_opt->required = NO;
+    out_dist_opt->description = "Output distance/accumulation map";
+
+    out_diff_opt = G_define_standard_option(G_OPT_R_OUTPUT);
+    out_diff_opt->key = "difference";
+    out_diff_opt->required = NO;
+    out_diff_opt->description = "Output elevation difference map";
+
+    flag_outs = G_define_flag();
+    flag_outs->key = 'o';
+    flag_outs->description =
+	_("Calculate parameters for outlets (outlet mode) instead of (default) streams");
+
+    flag_sub = G_define_flag();
+    flag_sub->key = 's';
+    flag_sub->description =
+	_("Calculate parameters for subbasins (ignored in stream mode)");
+
+    flag_near = G_define_flag();
+    flag_near->key = 'n';
+    flag_near->description =
+	_("Calculate nearest local maximum (ignored in downstream calculation)");
+
+    flag_segmentation = G_define_flag();
+    flag_segmentation->key = 'm';
+    flag_segmentation->description = _("Use memory swap (operation is slow)");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    if (!out_diff_opt->answer && !out_dist_opt->answer)
+	G_fatal_error(_("You must select at least one output maps: distance and (or) elevation"));
+    if (out_diff_opt->answer && !in_elev_opt->answer)
+	G_fatal_error(_("If you select elevation output, elevation is required"));
+
+    if (out_dist_opt->answer)
+	if (G_legal_filename(out_dist_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal distance name"),
+			  out_dist_opt->answer);
+
+    if (out_diff_opt->answer)
+	if (G_legal_filename(out_diff_opt->answer) < 0)
+	    G_fatal_error(_("<%s> is an illegal elevation difference name"),
+			  out_diff_opt->answer);
+
+    if (!strcmp(in_method_opt->answer, "upstream"))
+	method = UPSTREAM;
+    else if (!strcmp(in_method_opt->answer, "downstream"))
+	method = DOWNSTREAM;
+
+    outs = (flag_outs->answer != 0);
+    subs = (flag_sub->answer != 0);
+    near = (flag_near->answer != 0);
+    segmentation = (flag_segmentation->answer != 0);
+
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    G_begin_distance_calculations();
+
+    fifo_max = 4 * nrows * ncols;
+    fifo_points = (POINT *) G_malloc((fifo_max + 1) * sizeof(POINT));
+
+    if (!segmentation) {
+	G_message(_("ALL IN RAM CALCULATION - METHOD: %s"),
+		  method_name[method]);
+	MAP map_dirs, map_streams, map_distance, map_elevation,
+	    map_tmp_elevation;
+	CELL **streams, **dirs;
+	FCELL **distance;
+	FCELL **elevation = NULL;
+	FCELL **tmp_elevation = NULL;
+
+	ram_create_map(&map_streams, CELL_TYPE);
+	ram_read_map(&map_streams, in_stm_opt->answer, 1, CELL_TYPE);
+	ram_create_map(&map_dirs, CELL_TYPE);
+	ram_read_map(&map_dirs, in_dir_opt->answer, 1, CELL_TYPE);
+	ram_create_map(&map_distance, FCELL_TYPE);
+
+	streams = (CELL **) map_streams.map;
+	dirs = (CELL **) map_dirs.map;
+	distance = (FCELL **) map_distance.map;
+	number_of_streams = (int)map_streams.max + 1;
+
+	outlets_num =
+	    ram_find_outlets(streams, number_of_streams, dirs, subs, outs);
+	ram_init_distance(streams, distance, outlets_num, outs);
+	ram_release_map(&map_streams);
+
+	if (in_elev_opt->answer) {
+	    ram_create_map(&map_elevation, FCELL_TYPE);
+	    ram_read_map(&map_elevation, in_elev_opt->answer, 0, -1);
+	    elevation = (FCELL **) map_elevation.map;
+	}			/* map elevation will be replaced by elevation difference map */
+
+
+	if (method == DOWNSTREAM) {
+	    G_message(_("Calculate downstream parameters..."));
+	    for (j = 0; j < outlets_num; ++j) {
+		G_percent(j, outlets_num, 1);
+		ram_calculate_downstream(dirs, distance, elevation,
+					 outlets[j], outs);
+	    }
+	    G_percent(j, outlets_num, 1);
+
+	}
+	else if (method == UPSTREAM) {
+
+	    if (out_diff_opt->answer) {
+		ram_create_map(&map_tmp_elevation, FCELL_TYPE);
+		tmp_elevation = (FCELL **) map_tmp_elevation.map;
+	    }
+
+	    for (j = 0; j < outlets_num; ++j)
+		ram_fill_basins(outlets[j], distance, dirs);
+	    ram_calculate_upstream(distance, dirs, elevation, tmp_elevation,
+				   near);
+
+	}
+	else {
+	    G_fatal_error(_("Unrecognised method of processing"));
+	}			/* end methods */
+
+	if (out_diff_opt->answer) {
+	    ram_prep_null_elevation(distance, elevation);
+	    ram_write_map(&map_elevation, out_diff_opt->answer, FCELL_TYPE, 1,
+			  -1);
+	}
+
+	if (out_dist_opt->answer)
+	    ram_write_map(&map_distance, out_dist_opt->answer, FCELL_TYPE, 1,
+			  -1);
+
+	ram_release_map(&map_dirs);
+	ram_release_map(&map_distance);
+
+	if (in_elev_opt->answer)
+	    ram_release_map(&map_elevation);
+	if (in_elev_opt->answer && method == UPSTREAM)
+	    ram_release_map(&map_tmp_elevation);
+    }
+
+    if (segmentation) {
+	G_message(_("MEMORY SWAP CALCULATION - METHOD: %s MAY TAKE SOME TIME"),
+		  method_name[method]);
+	SEG map_dirs, map_streams, map_distance, map_elevation,
+	    map_tmp_elevation;
+	SEGMENT *streams, *dirs, *distance;
+	SEGMENT *elevation = NULL;
+	SEGMENT *tmp_elevation = NULL;
+
+	number_of_segs = (int)atof(opt_swapsize->answer);
+	if (method == DOWNSTREAM)
+	    number_of_segs = number_of_segs < 32 ? (int)(32 / 0.18) : number_of_segs / 0.18;
+	else			/* two elevation maps */
+	    number_of_segs = number_of_segs < 32 ? (int)(32 / 0.24) : number_of_segs / 0.24;
+
+	seg_create_map(&map_streams, SROWS, SCOLS, number_of_segs, CELL_TYPE);
+	seg_read_map(&map_streams, in_stm_opt->answer, 1, CELL_TYPE);
+	seg_create_map(&map_dirs, SROWS, SCOLS, number_of_segs, CELL_TYPE);
+	seg_read_map(&map_dirs, in_dir_opt->answer, 1, CELL_TYPE);
+	seg_create_map(&map_distance, SROWS, SCOLS, number_of_segs,
+		       FCELL_TYPE);
+
+	streams = &map_streams.seg;
+	dirs = &map_dirs.seg;
+	distance = &map_distance.seg;
+	number_of_streams = (int)map_streams.max + 1;
+
+	outlets_num =
+	    seg_find_outlets(streams, number_of_streams, dirs, subs, outs);
+	seg_init_distance(streams, distance, outlets_num, outs);
+	seg_release_map(&map_streams);
+
+	if (in_elev_opt->answer) {
+	    seg_create_map(&map_elevation, SROWS, SCOLS, number_of_segs,
+			   FCELL_TYPE);
+	    seg_read_map(&map_elevation, in_elev_opt->answer, 0, -1);
+	    elevation = &map_elevation.seg;
+	}			/* map elevation will be replaced by elevation difference map */
+
+	if (method == DOWNSTREAM) {
+	    G_message(_("Calculate downstream parameters..."));
+	    for (j = 0; j < outlets_num; ++j) {
+		G_percent(j, outlets_num, 1);
+		seg_calculate_downstream(dirs, distance, elevation,
+					 outlets[j], outs);
+	    }
+	    G_percent(j, outlets_num, 1);
+
+	}
+	else if (method == UPSTREAM) {
+
+	    if (out_diff_opt->answer) {
+		seg_create_map(&map_tmp_elevation, SROWS, SCOLS,
+			       number_of_segs, FCELL_TYPE);
+		tmp_elevation = &map_tmp_elevation.seg;
+	    }
+
+	    for (j = 0; j < outlets_num; ++j)
+		seg_fill_basins(outlets[j], distance, dirs);
+	    seg_calculate_upstream(distance, dirs, elevation, tmp_elevation,
+				   near);
+
+	}
+	else {
+	    G_fatal_error(_("Unrecognised method of processing"));
+	}			/* end methods */
+
+	if (out_dist_opt->answer)
+	    seg_write_map(&map_distance, out_dist_opt->answer, FCELL_TYPE, 1,
+			  -1);
+
+	if (out_diff_opt->answer) {
+	    seg_prep_null_elevation(distance, elevation);
+	    seg_write_map(&map_elevation, out_diff_opt->answer, FCELL_TYPE, 1,
+			  -1);
+	}
+
+	seg_release_map(&map_dirs);
+	seg_release_map(&map_distance);
+
+	if (in_elev_opt->answer)
+	    seg_release_map(&map_elevation);
+	if (in_elev_opt->answer && method == UPSTREAM)
+	    seg_release_map(&map_tmp_elevation);
+    }
+
+    G_free(fifo_points);
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.stream.distance/r.stream.distance.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.distance/r.stream.distance.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.distance/r.stream.distance.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,125 @@
+<h2>OPTIONS</h2>
+<dl>
+<dt><b>-o</b></dt>
+<dd>Outlets. Downstream method only. Calculate distance and relative  elevation
+to basin outlets instead of streams. It choose only last outlets in the network
+ignoring nodes.</dd>
+<dt><b>-s</b></dt>
+<dd>Subbasins. Downstream method only. Calculate distance and elevation to
+stream nodes instead of streams. It create distance and elevation parameters not
+for whole basins but for all elementary subbasins.</dd>
+<dt><b>-n</b></dt>
+<dd>Near. For upstream method only. Calculate distance and elevation to the
+nearest local maximum/divide. With the default option distance/elevation is
+calculated to the farthest possible maximum/divide
+</dd>
+<dt><b>streams</b></dt>
+<dd>Stream network: name of input stream map on which ordering will be performed
+produced by r.watershed or r.stream.extract. Because streams network produced by
+r.watershed and r.stream.extract may slighty differ in detail it is required to
+use both stream and direction map produced by the same module. Stream background
+shall have NULL value or zero value. Background values of NULL are by default
+produced by r.watershed and r.stream.extract. If not 0 or NULL use <a
+href="r.mapcalc.html">r.mapcalc</a> to set background values to null.  
+</dd>
+<dt><b>dirs</b></dt>
+<dd>Flow direction: name of input direction map produced by r.watershed or
+r.stream.extract. If r.stream.extract output map is used, it only has non-NULL
+values in places where streams occur. NULL (nodata) cells are ignored, zero and
+negative values are valid direction data if they vary from -8 to 8 (CCW from
+East in steps of 45 degrees). Direction map shall be of type CELL values. Region
+resolution and map resoultion must be the same. Also <em>stream</em> network map
+must have the same resolution. It is checked by default. If resolutions differ
+the module informs about it and stops. Region boundary and maps boundary may be
+differ but it may lead to unexpected results.</dd>
+<dt><b>elevation</b></dt>
+<dd>Elevation: name of input elevation map. Map can be of type CELL, FCELL or
+DCELL. It is not restricted to resolution of region settings as stream and
+dir.</dd>
+<dt><b>method</b></dt>
+<dd>It is possible to calculate distance with two method: <b>downstream</b> from
+any raster cell to the nearest stream cell/ junction cell or outlet or
+<b>upstream</b> from any cell upstream to the nearest maximum or divide</dd>
+</dl>
+
+<h2>OUTPUTS</h2>
+<dl>
+<dt><b>difference</b></dt>
+<dd>Returns elevation difference to the targer (outlet, node, stream, divide,
+maximum) along watercoures. The map is of FCELL type</dd>
+<dt><b>distance</b></dt>
+<dd>Returns distance to the targer (outlet, node, stream, divide, maximum) along
+watercoures. The map is of FCELL type</dd>
+</dl>
+
+<h2>DESCRIPTION</h2>
+<p>
+Module r.stream.distance may calculate distance using two methods: downstream
+and upstream.
+<p>
+The default is downstream method when it  calculate distance to streams and
+outlets and relative elevation to streams and outlets. The distance and
+elevation is calculated along watercourses. In outlets mode it can also
+calculate parameters for subbasins.
+<p>
+In streams mode (default) it calculates that parameters downstream to streams
+which are added as stream mask. In outlets mode there are some additional
+possibilities. If subbasin is off it calculate parameters only for last point of
+last (downstream) CELL. In subbasin mode it calculates parameters for every
+subbasin separately. Subbasin mode acts similar to subbasin mask. Streams file
+prepared to create basins and subbasins with r.stream.basins can use to to
+calculate distance and elevation parameters.
+<p>
+With upstream method it calculate distance to the local maximum or divide.
+Opposite to downstream method, where every cell has one and only one downstream
+cell in upstream method every cell has usually more than one upstream cell. So
+it is impossible to determine interchangeable path from any cell. The upstream
+method offers two alternative modes switched with -n flag: nearest local
+maximum/divide:  means the shortest path to local maximum and default option
+farthest maximum/divide means the longest path. In hydrological sense nearest
+mode means the shortest path which particle of water must run from divide to
+reach particular cell, while farthest mode means the possible longest path.
+
+<h2>NOTES</h2>
+<p>
+If there are more than one point or one stream networks and some separate points
+or separate streams networks are in catchment area defined by others it will
+results as in subbasin mode.  In stream mode subbasin options is ommited. Input
+maps must be in CELL format (default output of r.watershed, r.stream.order  and
+r.stream.extract).
+The distance are calculated in meters both for planimeters and
+Latitude-Longitude projections. The distance is calculated for flat areas not
+corrected by topography. Distance correction by topography may be done with
+following mapcalc formula:
+<p>
+<code>echo 'dist_corrected = sqrt(distance^2 + elevation ^2)'|r.mapcalc</code>
+<p>
+Module can work only if direction map, stream map and region has same settings.
+It is also required that stream map and direction map come from the same source.
+For lots of reason this limitation probably cannot be omitted.   this means if
+stream map comes from r.stream.extract also direction map from r.stream.extract
+must be used. If stream network was generated with MFD method also MFD direction
+map must be used.
+<p>
+Probably one of the most imortant features of r.stream.extract is the ability to
+calculate distnace not only for streams generated with r.stream.order, but also
+to any CELL map with resoultion coresponding to dirs map. It can be a lake,
+swamp, depression and lake boundaries even divided into smaller fragments each
+with its own category.
+
+<h2>SEE ALSO</h2>
+<em>
+<a href="r.watershed.html">r.watershed</a>,
+<a href="r.stream.extract.html">r.stream.extract</a>,
+<a href="r.stream.order.html">r.stream.order</a>,
+<a href="r.stream.basins.html">r.stream.basins</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+<a href="r.reclass.html">r.reclass</a>,
+</em>
+
+<h2>AUTHOR</h2>
+Jarek Jasiewicz, Adam Mickiewicz University, Geoecology and Geoinformation
+Institute.
+
+<p><i>Last changed: $Date: 2011-11-08 22:56:45 +0100 (Tue, 08 Nov 2011) $</i>
+

Added: grass-addons/grass7/grass7/raster/r.stream.extract/Makefile
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/Makefile	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/Makefile	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,12 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.stream.extract
+
+LIBES     = $(SEGMENTLIB) $(RASTERLIB) $(VECTORLIB) $(DBMILIB) $(GISLIB)
+DEPENDENCIES = $(SEGMENTDEP) $(RASTERDEP) $(VECTORDEP) $(DBMIDEP) $(GISDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/grass7/grass7/raster/r.stream.extract/bseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/bseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/bseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,159 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int bseg_open(BSEG *bseg, int srows, int scols, int nsegs_in_memory)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    bseg->filename = NULL;
+    bseg->fd = -1;
+    bseg->name = NULL;
+    bseg->mapset = NULL;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("bseg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (0 > (errflag = segment_format(fd, Rast_window_rows(),
+				      Rast_window_cols(), srows, scols,
+				      sizeof(char)))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("bseg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("bseg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("bseg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(bseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("bseg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("bseg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    bseg->filename = filename;
+    bseg->fd = fd;
+    return 0;
+}
+
+int bseg_close(BSEG *bseg)
+{
+    segment_release(&(bseg->seg));
+    close(bseg->fd);
+    unlink(bseg->filename);
+    if (bseg->name) {
+	G_free(bseg->name);
+	bseg->name = NULL;
+    }
+    if (bseg->mapset) {
+	G_free(bseg->mapset);
+	bseg->mapset = NULL;
+    }
+    return 0;
+}
+
+int bseg_put(BSEG *bseg, char *value, int row, int col)
+{
+    if (segment_put(&(bseg->seg), value, row, col) < 0) {
+	G_warning(_("bseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int bseg_put_row(BSEG *bseg, char *value, int row)
+{
+    if (segment_put_row(&(bseg->seg), value, row) < 0) {
+	G_warning(_("bseg_put_row(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int bseg_get(BSEG *bseg, char *value, int row, int col)
+{
+    if (segment_get(&(bseg->seg), value, row, col) < 0) {
+	G_warning(_("bseg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+
+int bseg_read_raster(BSEG *bseg, char *map_name, char *mapset)
+{
+    int row, nrows;
+    int col, ncols;
+    int map_fd;
+    CELL *buffer;
+    char cbuf;
+
+    bseg->name = NULL;
+    bseg->mapset = NULL;
+
+    map_fd = Rast_open_old(map_name, mapset);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    buffer = Rast_allocate_c_buf();
+    for (row = 0; row < nrows; row++) {
+	Rast_get_c_row(map_fd, buffer, row);
+	for (col = ncols; col >= 0; col--) {
+	    cbuf = (char) buffer[col];
+	    bseg_put(bseg, &cbuf, row, col);
+	}
+    }
+
+    Rast_close(map_fd);
+    G_free(buffer);
+
+    bseg->name = G_store(map_name);
+    bseg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int bseg_write_raster(BSEG *bseg, char *map_name)
+{
+    int map_fd;
+    int row, nrows;
+    int col, ncols;
+    CELL *buffer;
+    char value;
+
+    map_fd = Rast_open_c_new(map_name);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    buffer = Rast_allocate_c_buf();
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 1);
+	for (col = 0; col < ncols; col++) {
+	    bseg_get(bseg, &value, row, col);
+	    buffer[col] = value;
+	}
+	Rast_put_row(map_fd, buffer, CELL_TYPE);
+    }
+    G_percent(row, nrows, 1);    /* finish it */
+    G_free(buffer);
+    Rast_close(map_fd);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/close.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/close.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/close.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,322 @@
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include <grass/vector.h>
+#include <grass/dbmi.h>
+#include "local_proto.h"
+
+int close_streamvect(char *stream_vect)
+{
+    int i, r, c, r_nbr, c_nbr, done;
+    CELL stream_id, stream_nbr;
+    char aspect;
+    int next_node;
+    struct sstack
+    {
+	int stream_id;
+	int next_trib;
+    } *nodestack;
+    int top = 0, stack_step = 1000;
+    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+    struct Map_info Out;
+    static struct line_pnts *Points;
+    struct line_cats *Cats;
+    dbDriver *driver;
+    dbHandle handle;
+    dbString table_name, dbsql, valstr;
+    struct field_info *Fi;
+    char *cat_col_name = "cat", buf[2000];
+    struct Cell_head window;
+    double north_offset, west_offset, ns_res, ew_res;
+    int next_cat;
+
+    G_message(_("Writing vector map <%s>..."), stream_vect);
+
+    if (0 > Vect_open_new(&Out, stream_vect, 0)) {
+	G_fatal_error(_("Unable to create vector map <%s>"), stream_vect);
+    }
+
+    nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack));
+
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+
+    G_get_set_window(&window);
+    ns_res = window.ns_res;
+    ew_res = window.ew_res;
+    north_offset = window.north - 0.5 * ns_res;
+    west_offset = window.west + 0.5 * ew_res;
+
+    next_cat = n_stream_nodes + 1;
+
+    for (i = 0; i < n_outlets; i++, next_cat++) {
+	G_percent(i, n_outlets, 2);
+	r = outlets[i].r;
+	c = outlets[i].c;
+	cseg_get(&stream, &stream_id, r, c);
+
+	if (!stream_id)
+	    continue;
+
+	Vect_reset_line(Points);
+	Vect_reset_cats(Cats);
+
+	/* outlet */
+	Vect_cat_set(Cats, 1, stream_id);
+	Vect_cat_set(Cats, 2, 2);
+	Vect_append_point(Points, west_offset + c * ew_res,
+			  north_offset - r * ns_res, 0);
+	Vect_write_line(&Out, GV_POINT, Points, Cats);
+
+	/* add root node to stack */
+	G_debug(3, "add root node");
+	top = 0;
+	nodestack[top].stream_id = stream_id;
+	nodestack[top].next_trib = 0;
+
+	/* depth first post order traversal */
+	G_debug(3, "traverse");
+	while (top >= 0) {
+
+	    done = 1;
+	    stream_id = nodestack[top].stream_id;
+	    G_debug(3, "stream_id %d", stream_id);
+	    if (nodestack[top].next_trib < stream_node[stream_id].n_trib) {
+		/* add to stack */
+		next_node =
+		    stream_node[stream_id].trib[nodestack[top].next_trib];
+		G_debug(3, "add to stack: next %d, trib %d, n trib %d",
+			next_node, nodestack[top].next_trib,
+			stream_node[stream_id].n_trib);
+		nodestack[top].next_trib++;
+		top++;
+		if (top >= stack_step) {
+		    /* need more space */
+		    stack_step += 1000;
+		    nodestack =
+			(struct sstack *)G_realloc(nodestack,
+						   stack_step *
+						   sizeof(struct sstack));
+		}
+		nodestack[top].next_trib = 0;
+		nodestack[top].stream_id = next_node;
+		done = 0;
+		G_debug(3, "go further down");
+	    }
+	    if (done) {
+		G_debug(3, "write stream segment");
+
+		Vect_reset_line(Points);
+		Vect_reset_cats(Cats);
+
+		r_nbr = stream_node[stream_id].r;
+		c_nbr = stream_node[stream_id].c;
+
+		cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
+		if (stream_nbr <= 0)
+		    G_fatal_error("stream id %d not set, top is %d, parent is %d", stream_id, top, nodestack[top - 1].stream_id);
+
+		Vect_cat_set(Cats, 1, stream_id);
+		if (stream_node[stream_id].n_trib == 0)
+		    Vect_cat_set(Cats, 2, 0);
+		else
+		    Vect_cat_set(Cats, 2, 1);
+
+		Vect_append_point(Points, west_offset + c_nbr * ew_res,
+				  north_offset - r_nbr * ns_res, 0);
+
+		Vect_write_line(&Out, GV_POINT, Points, Cats);
+
+		bseg_get(&asp, &aspect, r_nbr, c_nbr);
+		while (aspect > 0) {
+		    r_nbr = r_nbr + asp_r[(int)aspect];
+		    c_nbr = c_nbr + asp_c[(int)aspect];
+		    
+		    cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
+		    if (stream_nbr <= 0)
+			G_fatal_error("stream id not set while tracing");
+
+		    Vect_append_point(Points, west_offset + c_nbr * ew_res,
+				      north_offset - r_nbr * ns_res, 0);
+		    if (stream_nbr != stream_id) {
+			/* first point of parent stream */
+			break;
+		    }
+		    bseg_get(&asp, &aspect, r_nbr, c_nbr);
+		}
+
+		Vect_write_line(&Out, GV_LINE, Points, Cats);
+
+		top--;
+	    }
+	}
+    }
+    G_percent(n_outlets, n_outlets, 1);	/* finish it */
+
+    G_message(_("Writing vector attribute table"));
+
+    /* Prepeare strings for use in db_* calls */
+    db_init_string(&dbsql);
+    db_init_string(&valstr);
+    db_init_string(&table_name);
+    db_init_handle(&handle);
+
+    /* Preparing database for use */
+    /* Create database for new vector map */
+    Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
+    driver = db_start_driver_open_database(Fi->driver,
+					   Vect_subst_var(Fi->database,
+							          &Out));
+    if (driver == NULL) {
+	G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
+    }
+
+    G_debug(1, "table: %s", Fi->table);
+    G_debug(1, "driver: %s", Fi->driver);
+    G_debug(1, "database: %s", Fi->database);
+
+    sprintf(buf,
+	    "create table %s (%s integer, stream_type varchar(20), type_code integer)",
+	    Fi->table, cat_col_name);
+    db_set_string(&dbsql, buf);
+
+    if (db_execute_immediate(driver, &dbsql) != DB_OK) {
+	db_close_database(driver);
+	db_shutdown_driver(driver);
+	G_fatal_error(_("Cannot create table: %s"), db_get_string(&dbsql));
+    }
+
+    if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK)
+	G_warning(_("Cannot create index"));
+
+    if (db_grant_on_table(driver, Fi->table, DB_PRIV_SELECT,
+			  DB_GROUP | DB_PUBLIC) != DB_OK)
+	G_fatal_error(_("Cannot grant privileges on table %s"), Fi->table);
+
+    db_begin_transaction(driver);
+
+    /* stream nodes */
+    for (i = 1; i <= n_stream_nodes; i++) {
+
+	sprintf(buf, "insert into %s values ( %d, \'%s\', %d )",
+		Fi->table, i,
+		(stream_node[i].n_trib > 0 ? "intermediate" : "start"),
+		(stream_node[i].n_trib > 0));
+
+	db_set_string(&dbsql, buf);
+
+	if (db_execute_immediate(driver, &dbsql) != DB_OK) {
+	    db_close_database(driver);
+	    db_shutdown_driver(driver);
+	    G_fatal_error(_("Cannot insert new row: %s"),
+			  db_get_string(&dbsql));
+	}
+    }
+
+    db_commit_transaction(driver);
+    db_close_database_shutdown_driver(driver);
+
+    Vect_map_add_dblink(&Out, 1, NULL, Fi->table,
+			cat_col_name, Fi->database, Fi->driver);
+
+    G_debug(1, "close vector");
+
+    Vect_hist_command(&Out);
+    Vect_build(&Out);
+    Vect_close(&Out);
+
+    G_free(nodestack);
+
+    return 1;
+}
+
+
+int close_maps(char *stream_rast, char *stream_vect, char *dir_rast)
+{
+    int stream_fd, dir_fd, r, c, i;
+    CELL *cell_buf1, *cell_buf2;
+    struct History history;
+    char flag_value;
+    CELL stream_id;
+    char aspect;
+
+    /* cheating... */
+    stream_fd = dir_fd = -1;
+    cell_buf1 = cell_buf2 = NULL;
+
+    G_message(_("Writing raster %s"),
+              (stream_rast != NULL) + (dir_rast != NULL) > 1 ? _("maps") : _("map"));
+
+    /* write requested output rasters */
+    if (stream_rast) {
+	stream_fd = Rast_open_new(stream_rast, CELL_TYPE);
+	cell_buf1 = Rast_allocate_c_buf();
+    }
+    if (dir_rast) {
+	dir_fd = Rast_open_new(dir_rast, CELL_TYPE);
+	cell_buf2 = Rast_allocate_c_buf();
+    }
+
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+	if (stream_rast)
+	    Rast_set_c_null_value(cell_buf1, ncols);	/* reset row to all NULL */
+	if (dir_rast)
+	    Rast_set_c_null_value(cell_buf2, ncols);	/* reset row to all NULL */
+
+	for (c = 0; c < ncols; c++) {
+	    if (stream_rast) {
+		cseg_get(&stream, &stream_id, r, c);
+		if (stream_id)
+		    cell_buf1[c] = stream_id;
+	    }
+	    if (dir_rast) {
+		bseg_get(&bitflags, &flag_value, r, c);
+		if (!FLAG_GET(flag_value, NULLFLAG)) {
+		    bseg_get(&asp, &aspect, r, c);
+		    cell_buf2[c] = aspect;
+		}
+	    }
+	    
+	}
+	if (stream_rast)
+	    Rast_put_row(stream_fd, cell_buf1, CELL_TYPE);
+	if (dir_rast)
+	    Rast_put_row(dir_fd, cell_buf2, CELL_TYPE);
+    }
+    G_percent(nrows, nrows, 2);	/* finish it */
+
+    if (stream_rast) {
+	Rast_close(stream_fd);
+	G_free(cell_buf1);
+	Rast_short_history(stream_rast, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(stream_rast, &history);
+    }
+    if (dir_rast) {
+	Rast_close(dir_fd);
+	G_free(cell_buf2);
+	Rast_short_history(dir_rast, "raster", &history);
+	Rast_command_history(&history);
+	Rast_write_history(dir_rast, &history);
+    }
+
+    /* close stream vector */
+    if (stream_vect) {
+	if (close_streamvect(stream_vect) < 0)
+	    G_fatal_error(_("Unable to write vector map <%s>"), stream_vect);
+    }
+
+    /* rearranging desk chairs on the Titanic... */
+    G_free(outlets);
+
+    /* free stream nodes */
+    for (i = 1; i <= n_stream_nodes; i++) {
+	if (stream_node[i].n_alloc > 0) {
+	    G_free(stream_node[i].trib);
+	}
+    }
+    G_free(stream_node);
+
+    return 1;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/cseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/cseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/cseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,154 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int cseg_open(CSEG *cseg, int srows, int scols, int nsegs_in_memory)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    cseg->filename = NULL;
+    cseg->fd = -1;
+    cseg->name = NULL;
+    cseg->mapset = NULL;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("cseg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (0 >
+	(errflag =
+	 segment_format(fd, Rast_window_rows(), Rast_window_cols(), srows, scols,
+			sizeof(CELL)))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("cseg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("cseg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("cseg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(cseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("cseg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("cseg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    cseg->filename = filename;
+    cseg->fd = fd;
+    return 0;
+}
+
+int cseg_close(CSEG *cseg)
+{
+    segment_release(&(cseg->seg));
+    close(cseg->fd);
+    unlink(cseg->filename);
+    if (cseg->name) {
+	G_free(cseg->name);
+	cseg->name = NULL;
+    }
+    if (cseg->mapset) {
+	G_free(cseg->mapset);
+	cseg->mapset = NULL;
+    }
+    return 0;
+}
+
+int cseg_put(CSEG *cseg, CELL *value, int row, int col)
+{
+    if (segment_put(&(cseg->seg), value, row, col) < 0) {
+	G_warning(_("cseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int cseg_put_row(CSEG *cseg, CELL *value, int row)
+{
+    if (segment_put_row(&(cseg->seg), value, row) < 0) {
+	G_warning(_("cseg_put_row(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int cseg_get(CSEG *cseg, CELL *value, int row, int col)
+{
+    if (segment_get(&(cseg->seg), value, row, col) < 0) {
+	G_warning(_("cseg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int cseg_read_raster(CSEG *cseg, char *map_name, char *mapset)
+{
+    int row, nrows;
+    int map_fd;
+    CELL *buffer;
+
+    cseg->name = NULL;
+    cseg->mapset = NULL;
+
+    map_fd = Rast_open_old(map_name, mapset);
+    nrows = Rast_window_rows();
+    buffer = Rast_allocate_c_buf();
+    for (row = 0; row < nrows; row++) {
+	Rast_get_c_row(map_fd, buffer, row);
+	if (segment_put_row(&(cseg->seg), buffer, row) < 0) {
+	    G_free(buffer);
+	    Rast_close(map_fd);
+	    G_warning(_("cseg_read_cell(): unable to segment put row for <%s> in <%s>"),
+		    map_name, mapset);
+	    return (-1);
+	}
+    }
+
+    Rast_close(map_fd);
+    G_free(buffer);
+
+    cseg->name = G_store(map_name);
+    cseg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int cseg_write_raster(CSEG *cseg, char *map_name)
+{
+    int map_fd;
+    int row, nrows;
+    CELL *buffer;
+
+    map_fd = Rast_open_c_new(map_name);
+    nrows = Rast_window_rows();
+    buffer = Rast_allocate_c_buf();
+    segment_flush(&(cseg->seg));
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 1);
+	segment_get_row(&(cseg->seg), buffer, row);
+	Rast_put_row(map_fd, buffer, CELL_TYPE);
+    }
+    G_percent(row, nrows, 1);    /* finish it */
+    G_free(buffer);
+    Rast_close(map_fd);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/del_streams.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/del_streams.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/del_streams.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,194 @@
+#include <stdlib.h>
+#include <math.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+/* get stream segment length */
+int seg_length(CELL stream_id, CELL *next_stream_id)
+{
+    int r, c, r_nbr, c_nbr;
+    int slength = 1;
+    CELL curr_stream;
+    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+    char aspect;
+
+    r = stream_node[stream_id].r;
+    c = stream_node[stream_id].c;
+    if (next_stream_id)
+	*next_stream_id = stream_id;
+
+    /* get next downstream point */
+    bseg_get(&asp, &aspect, r, c);
+    while (aspect > 0) {
+	r_nbr = r + asp_r[(int)aspect];
+	c_nbr = c + asp_c[(int)aspect];
+
+	/* user-defined depression */
+	if (r_nbr == r && c_nbr == c)
+	    break;
+	/* outside region */
+	if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
+	    break;
+	/* next stream */
+	cseg_get(&stream, &curr_stream, r_nbr, c_nbr);
+	if (next_stream_id)
+	    *next_stream_id = curr_stream;
+	if (curr_stream != stream_id)
+	    break;
+	slength++;
+	r = r_nbr;
+	c = c_nbr;
+	bseg_get(&asp, &aspect, r, c);
+    }
+
+    return slength;
+}
+
+/* change downstream id: update or remove */
+int update_stream_id(CELL stream_id, CELL new_stream_id)
+{
+    int i, r, c, r_nbr, c_nbr;
+    CELL new_stream = new_stream_id;
+    CELL curr_stream;
+    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+    char aspect;
+
+    r = stream_node[stream_id].r;
+    c = stream_node[stream_id].c;
+    cseg_get(&stream, &curr_stream, r, c);
+    if (curr_stream != stream_id)
+	G_fatal_error("update downstream id: curr_stream != stream_id");
+    cseg_put(&stream, &new_stream, r, c);
+    curr_stream = stream_id;
+
+    /* get next downstream point */
+    bseg_get(&asp, &aspect, r, c);
+    while (aspect > 0) {
+	r_nbr = r + asp_r[(int)aspect];
+	c_nbr = c + asp_c[(int)aspect];
+
+	/* user-defined depression */
+	if (r_nbr == r && c_nbr == c)
+	    break;
+	/* outside region */
+	if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
+	    break;
+	/* next stream */
+	cseg_get(&stream, &curr_stream, r_nbr, c_nbr);
+	if (curr_stream != stream_id)
+	    break;
+	r = r_nbr;
+	c = c_nbr;
+	cseg_put(&stream, &new_stream, r, c);
+	bseg_get(&asp, &aspect, r, c);
+    }
+    
+    if (curr_stream <= 0)
+	return curr_stream;
+
+    /* update tributaries */
+    if (curr_stream != stream_id) {
+	int last_i = -1;
+	
+	for (i = 0; i < stream_node[curr_stream].n_trib; i++) {
+	    if (stream_node[curr_stream].trib[i] == stream_id) {
+		if (new_stream_id) {
+		    stream_node[curr_stream].trib[i] = new_stream_id;
+		}
+		else {
+		    stream_node[curr_stream].n_trib--;
+		    stream_node[curr_stream].trib[i] = stream_node[curr_stream].trib[stream_node[curr_stream].n_trib];
+		    stream_node[curr_stream].trib[stream_node[curr_stream].n_trib] = 0;
+		}
+		last_i = i;
+		break;
+	    }
+	}
+	for (i = 0; i < stream_node[curr_stream].n_trib; i++) {
+	    if (stream_node[curr_stream].trib[i] == stream_id) {
+		G_warning("last_i %d, i %d", last_i, i);
+		G_warning("failed updating stream %d at node %d", stream_id, curr_stream);
+	    }
+	}
+    }
+
+    return curr_stream;
+}
+
+/* delete stream segments shorter than threshold */
+int del_streams(int min_length)
+{
+    int i;
+    int n_deleted = 0;
+    CELL curr_stream, stream_id;
+    int other_trib, tmp_trib;
+    int slength;
+
+    G_message(_("Deleting stream segments shorter than %d cells..."), min_length);
+
+    /* TODO: proceed from stream heads to outlets
+     *       -> use depth first post order traversal */
+
+    /* go through all nodes */
+    for (i = 1; i <= n_stream_nodes; i++) {
+	G_percent(i, n_stream_nodes, 2);
+
+	/* not a stream head */
+	if (stream_node[i].n_trib > 0)
+	    continue;
+
+	/* already deleted */
+	cseg_get(&stream, &curr_stream, stream_node[i].r, stream_node[i].c);
+	if (curr_stream == 0)
+	    continue;
+
+	/* get length counted as n cells */
+	if ((slength = seg_length(i, &curr_stream)) >= min_length)
+	    continue;
+
+	stream_id = i;
+	
+	/* check n sibling tributaries */
+	if (curr_stream != stream_id) {
+	    /* only one sibling tributary */
+	    if (stream_node[curr_stream].n_trib == 2) {
+		if (stream_node[curr_stream].trib[0] != stream_id)
+		    other_trib = stream_node[curr_stream].trib[0];
+		else
+		    other_trib = stream_node[curr_stream].trib[1];
+
+		/* other trib is also stream head */
+		if (stream_node[other_trib].n_trib == 0) {
+		    /* use shorter one */
+		    if (seg_length(other_trib, NULL) < slength) {
+			tmp_trib = stream_id;
+			stream_id = other_trib;
+			other_trib = tmp_trib;
+		    }
+		}
+		update_stream_id(stream_id, 0);
+		n_deleted++;
+		
+		/* update downstream IDs */
+		update_stream_id(curr_stream, other_trib);
+	    }
+	    /* more than one other tributary */
+	    else {
+		update_stream_id(stream_id, 0);
+		n_deleted++;
+	    }
+	}
+	/* stream head is also outlet */
+	else {
+	    update_stream_id(stream_id, 0);
+	    n_deleted++;
+	}
+    }
+
+    G_verbose_message(_("%d stream segments deleted"), n_deleted);
+
+    return n_deleted;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/do_astar.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/do_astar.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/do_astar.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,291 @@
+#include <stdlib.h>
+#include <math.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+#define GET_PARENT(c) ((((c) - 2) >> 3) + 1)
+#define GET_CHILD(p) (((p) << 3) - 6)
+
+HEAP_PNT heap_drop(void);
+int sift_up(GW_LARGE_INT, HEAP_PNT);
+double get_slope(CELL, CELL, double);
+
+int do_astar(void)
+{
+    int r, c, r_nbr, c_nbr, ct_dir;
+    GW_LARGE_INT first_cum, count;
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+    CELL ele_val, ele_up, ele_nbr[8];
+    WAT_ALT wa;
+    char asp_val;
+    char flag_value, is_in_list, is_worked;
+    HEAP_PNT heap_p;
+    /* sides
+     * |7|1|4|
+     * |2| |3|
+     * |5|0|6|
+     */
+    int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1 };
+    int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2 };
+    double dx, dy, dist_to_nbr[8], ew_res, ns_res;
+    double slope[8];
+    struct Cell_head window;
+    int skip_me;
+
+    count = 0;
+
+    first_cum = n_points;
+
+    G_message(_("A* Search..."));
+
+    Rast_get_window(&window);
+
+    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	/* get r, c (r_nbr, c_nbr) for neighbours */
+	r_nbr = nextdr[ct_dir];
+	c_nbr = nextdc[ct_dir];
+	/* account for rare cases when ns_res != ew_res */
+	dy = abs(r_nbr) * window.ns_res;
+	dx = abs(c_nbr) * window.ew_res;
+	if (ct_dir < 4)
+	    dist_to_nbr[ct_dir] = dx + dy;
+	else
+	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
+    }
+    ew_res = window.ew_res;
+    ns_res = window.ns_res;
+    
+    while (heap_size > 0) {
+	G_percent(count++, n_points, 1);
+	if (count > n_points)
+	    G_fatal_error(_("BUG in A* Search: %lld surplus points"),
+	                  heap_size);
+
+	if (heap_size > n_points)
+	    G_fatal_error
+		(_("BUG in A* Search: too many points in heap %lld, should be %lld"),
+		 heap_size, n_points);
+
+	heap_p = heap_drop();
+
+	r = heap_p.pnt.r;
+	c = heap_p.pnt.c;
+
+	ele_val = heap_p.ele;
+
+	for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	    /* get r, c (r_nbr, c_nbr) for neighbours */
+	    r_nbr = r + nextdr[ct_dir];
+	    c_nbr = c + nextdc[ct_dir];
+	    slope[ct_dir] = ele_nbr[ct_dir] = 0;
+	    skip_me = 0;
+
+	    /* check that neighbour is within region */
+	    if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
+		continue;
+
+	    bseg_get(&bitflags, &flag_value, r_nbr, c_nbr);
+	    is_in_list = FLAG_GET(flag_value, INLISTFLAG);
+	    is_worked = FLAG_GET(flag_value, WORKEDFLAG);
+	    if (!is_worked) {
+		seg_get(&watalt, (char *)&wa, r_nbr, c_nbr);
+		ele_nbr[ct_dir] = wa.ele;
+		slope[ct_dir] = get_slope(ele_val, ele_nbr[ct_dir],
+			                  dist_to_nbr[ct_dir]);
+	    }
+	    /* avoid diagonal flow direction bias */
+	    if (!is_in_list) {
+		if (ct_dir > 3 && slope[ct_dir] > 0) {
+		    if (slope[nbr_ew[ct_dir]] > 0) {
+			/* slope to ew nbr > slope to center */
+			if (slope[ct_dir] <
+			    get_slope(ele_nbr[nbr_ew[ct_dir]],
+				       ele_nbr[ct_dir], ew_res))
+			    skip_me = 1;
+		    }
+		    if (!skip_me && slope[nbr_ns[ct_dir]] > 0) {
+			/* slope to ns nbr > slope to center */
+			if (slope[ct_dir] <
+			    get_slope(ele_nbr[nbr_ns[ct_dir]],
+				       ele_nbr[ct_dir], ns_res))
+			    skip_me = 1;
+		    }
+		}
+	    }
+
+	    if (is_in_list == 0 && skip_me == 0) {
+		ele_up = ele_nbr[ct_dir];
+		asp_val = drain[r_nbr - r + 1][c_nbr - c + 1];
+		bseg_put(&asp, &asp_val, r_nbr, c_nbr);
+		heap_add(r_nbr, c_nbr, ele_up);
+		FLAG_SET(flag_value, INLISTFLAG);
+		bseg_put(&bitflags, &flag_value, r_nbr, c_nbr);
+	    }
+	    else if (is_in_list && is_worked == 0) {
+		if (FLAG_GET(flag_value, EDGEFLAG)) {
+		    /* neighbour is edge in list, not yet worked */
+		    bseg_get(&asp, &asp_val, r_nbr, c_nbr);
+		    if (asp_val < 0) {
+			/* adjust flow direction for edge cell */
+			asp_val = drain[r_nbr - r + 1][c_nbr - c + 1];
+			bseg_put(&asp, &asp_val, r_nbr, c_nbr);
+		    }
+		}
+		else if (FLAG_GET(flag_value, DEPRFLAG)) {
+		    G_debug(3, "real depression");
+		    /* neighbour is inside real depression, not yet worked */
+		    bseg_get(&asp, &asp_val, r_nbr, c_nbr);
+		    if (asp_val == 0 && ele_val <= ele_nbr[ct_dir]) {
+			asp_val = drain[r_nbr - r + 1][c_nbr - c + 1];
+			bseg_put(&asp, &asp_val, r_nbr, c_nbr);
+			FLAG_UNSET(flag_value, DEPRFLAG);
+			bseg_put(&bitflags, &flag_value, r_nbr, c_nbr);
+		    }
+		}
+	    }
+	}    /* end neighbours */
+	/* add astar points to sorted list for flow accumulation and stream extraction */
+	first_cum--;
+	seg_put(&astar_pts, (char *)&heap_p.pnt, 0, first_cum);
+	bseg_get(&bitflags, &flag_value, r, c);
+	FLAG_SET(flag_value, WORKEDFLAG);
+	bseg_put(&bitflags, &flag_value, r, c);
+    }    /* end A* search */
+
+    G_percent(n_points, n_points, 1);	/* finish it */
+
+    return 1;
+}
+
+/*
+ * compare function for heap
+ * returns 1 if point1 < point2 else 0
+ */
+int heap_cmp(HEAP_PNT *a, HEAP_PNT *b)
+{
+    if (a->ele < b->ele)
+	return 1;
+    else if (a->ele == b->ele) {
+	if (a->added < b->added)
+	    return 1;
+    }
+    return 0;
+}
+
+int sift_up(GW_LARGE_INT start, HEAP_PNT child_p)
+{
+    GW_LARGE_INT parent, child;
+    HEAP_PNT heap_p;
+
+    child = start;
+
+    while (child > 1) {
+	parent = GET_PARENT(child);
+	seg_get(&search_heap, (char *)&heap_p, 0, parent);
+
+	/* push parent point down if child is smaller */
+	if (heap_cmp(&child_p, &heap_p)) {
+	    seg_put(&search_heap, (char *)&heap_p, 0, child);
+	    child = parent;
+	}
+	else
+	    /* no more sifting up, found slot for child */
+	    break;
+    }
+
+    /* add child to heap */
+    seg_put(&search_heap, (char *)&child_p, 0, child);
+
+    return 0;
+}
+
+/*
+ * add item to heap
+ * returns heap_size
+ */
+GW_LARGE_INT heap_add(int r, int c, CELL ele)
+{
+    HEAP_PNT heap_p;
+    
+    /* add point to next free position */
+
+    heap_size++;
+
+    heap_p.added = nxt_avail_pt;
+    heap_p.ele = ele;
+    heap_p.pnt.r = r;
+    heap_p.pnt.c = c;
+
+    nxt_avail_pt++;
+
+    /* sift up: move new point towards top of heap */
+    sift_up(heap_size, heap_p);
+
+    return heap_size;
+}
+
+/*
+ * drop item from heap
+ * returns heap size
+ */
+HEAP_PNT heap_drop(void)
+{
+    GW_LARGE_INT child, childr, parent;
+    GW_LARGE_INT i;
+    HEAP_PNT child_p, childr_p, last_p, root_p;
+
+    seg_get(&search_heap, (char *)&last_p, 0, heap_size);
+    seg_get(&search_heap, (char *)&root_p, 0, 1);
+
+    if (heap_size == 1) {
+	heap_size = 0;
+	return root_p;
+    }
+
+    parent = 1;
+    while ((child = GET_CHILD(parent)) < heap_size) {
+
+	seg_get(&search_heap, (char *)&child_p, 0, child);
+
+	if (child < heap_size) {
+	    childr = child + 1;
+	    i = child + 8;
+	    while (childr < heap_size && childr < i) {
+		seg_get(&search_heap, (char *)&childr_p, 0, childr);
+		if (heap_cmp(&childr_p, &child_p)) {
+		    child = childr;
+		    child_p = childr_p;
+		}
+		childr++;
+	    }
+	}
+
+	if (heap_cmp(&last_p, &child_p)) {
+	    break;
+	}
+
+	/* move hole down */
+	seg_put(&search_heap, (char *)&child_p, 0, parent);
+	parent = child;
+    }
+
+    /* fill hole */
+    if (parent < heap_size) {
+	seg_put(&search_heap, (char *)&last_p, 0, parent);
+    }
+
+    /* the actual drop */
+    heap_size--;
+
+    return root_p;
+}
+
+double get_slope(CELL ele, CELL up_ele, double dist)
+{
+    if (ele >= up_ele)
+	return 0.0;
+    else
+	return (double)(up_ele - ele) / dist;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/dseg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/dseg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/dseg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,156 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int dseg_open(DSEG *dseg, int srows, int scols, int nsegs_in_memory)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    dseg->filename = NULL;
+    dseg->fd = -1;
+    dseg->name = NULL;
+    dseg->mapset = NULL;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("dseg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (0 >
+	(errflag =
+	 segment_format(fd, Rast_window_rows(), Rast_window_cols(), srows, scols,
+			sizeof(DCELL)))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("dseg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("dseg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("dseg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(dseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("dseg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("dseg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    dseg->filename = filename;
+    dseg->fd = fd;
+    return 0;
+}
+
+int dseg_close(DSEG *dseg)
+{
+    segment_release(&(dseg->seg));
+    close(dseg->fd);
+    unlink(dseg->filename);
+    if (dseg->name) {
+	G_free(dseg->name);
+	dseg->name = NULL;
+    }
+    if (dseg->mapset) {
+	G_free(dseg->mapset);
+	dseg->mapset = NULL;
+    }
+    return 0;
+}
+
+int dseg_put(DSEG *dseg, DCELL *value, int row, int col)
+{
+    if (segment_put(&(dseg->seg), (DCELL *) value, row, col) < 0) {
+	G_warning(_("dseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int dseg_put_row(DSEG *dseg, DCELL *value, int row)
+{
+    if (segment_put_row(&(dseg->seg), (DCELL *) value, row) < 0) {
+	G_warning(_("dseg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int dseg_get(DSEG *dseg, DCELL *value, int row, int col)
+{
+    if (segment_get(&(dseg->seg), (DCELL *) value, row, col) < 0) {
+	G_warning(_("dseg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int dseg_read_raster(DSEG *dseg, char *map_name, char *mapset)
+{
+    int row, nrows, ncols;
+    int map_fd;
+    DCELL *dbuffer;
+
+    dseg->name = NULL;
+    dseg->mapset = NULL;
+
+    map_fd = Rast_open_old(map_name, mapset);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    dbuffer = Rast_allocate_d_buf();
+    for (row = 0; row < nrows; row++) {
+	Rast_get_d_row(map_fd, dbuffer, row);
+	if (segment_put_row(&(dseg->seg), (DCELL *) dbuffer, row) < 0) {
+	    G_free(dbuffer);
+	    Rast_close(map_fd);
+	    G_warning(_("dseg_read_raster(): unable to segment put row for <%s> in <%s>"),
+		    map_name, mapset);
+	    return (-1);
+	}
+    }
+
+    Rast_close(map_fd);
+    G_free(dbuffer);
+
+    dseg->name = G_store(map_name);
+    dseg->mapset = G_store(mapset);
+
+    return 0;
+}
+
+int dseg_write_cellfile(DSEG *dseg, char *map_name)
+{
+    int map_fd;
+    int row, nrows, ncols;
+    DCELL *dbuffer;
+
+    map_fd = Rast_open_new(map_name, DCELL_TYPE);
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    dbuffer = Rast_allocate_d_buf();
+    segment_flush(&(dseg->seg));
+    for (row = 0; row < nrows; row++) {
+	G_percent(row, nrows, 1);
+	segment_get_row(&(dseg->seg), (DCELL *) dbuffer, row);
+	Rast_put_row(map_fd, dbuffer, DCELL_TYPE);
+    }
+    G_percent(row, nrows, 1);    /* finish it */
+    G_free(dbuffer);
+    Rast_close(map_fd);
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/flag.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/flag.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/flag.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,36 @@
+#ifndef __FLAG_H__
+#define __FLAG_H__
+
+/* a set of routines that allow the programmer to "flag" cells in a
+ * raster map. A flag is of type unsigned char, i.e. 8 bits can be set. 
+ *
+ * int flag_set(flag, bitno)
+ *     sets the flag at position bitno to one.
+ *
+ * int flag_unset(flag, bitno)
+ *     sets the flag at position bitno to zero.
+ *
+ * int flag_get(flag, bitno)
+ *     checks if the flag is set at postion bitno.
+ *
+ * Examples:
+ * set flag at position 0: FLAG_SET(flag, 0)
+ * unset (clear) flag at position 7: FLAG_UNSET(flag, 7)
+ * check flag at position 5: is_set_at_5 = FLAG_GET(flag, 5)
+ */
+
+/* flag positions */
+#define NULLFLAG         0      /* elevation is NULL */
+#define EDGEFLAG         1      /* edge cell */
+#define INLISTFLAG       2      /* in open A* list */
+#define WORKEDFLAG       3      /* in closed A* list/ accumulation done */
+#define STREAMFLAG       4      /* stream */
+#define DEPRFLAG         5      /* real depression */
+#define WORKED2FLAG      6      /* extraction done */
+/* last bit is unused */
+
+#define FLAG_SET(flag,bitno) ((flag) |= (1 << (bitno)))
+#define FLAG_UNSET(flag,bitno) ((flag) &= ~(1 << (bitno)))
+#define FLAG_GET(flag,bitno) ((flag) & (1 << (bitno)))
+
+#endif /* __FLAG_H__ */

Added: grass-addons/grass7/grass7/raster/r.stream.extract/init_search.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/init_search.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/init_search.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,122 @@
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+int init_search(int depr_fd)
+{
+    int r, c, r_nbr, c_nbr, ct_dir;
+    CELL *depr_buf, ele_value;
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+    char flag_value, flag_value_nbr, is_null;
+    WAT_ALT wa;
+    char asp_value;
+    GW_LARGE_INT n_depr_cells = 0;
+
+    nxt_avail_pt = heap_size = 0;
+
+    /* load edge cells and real depressions to A* heap */
+    if (depr_fd >= 0)
+	depr_buf = Rast_allocate_buf(CELL_TYPE);
+    else
+	depr_buf = NULL;
+
+    G_message(_("Initializing A* Search..."));
+    for (r = 0; r < nrows; r++) {
+	G_percent(r, nrows, 2);
+
+	if (depr_fd >= 0) {
+	    Rast_get_row(depr_fd, depr_buf, r, CELL_TYPE);
+	}
+
+	for (c = 0; c < ncols; c++) {
+
+	    bseg_get(&bitflags, &flag_value, r, c);
+	    is_null = FLAG_GET(flag_value, NULLFLAG);
+
+	    if (is_null)
+		continue;
+
+	    asp_value = 0;
+	    if (r == 0 || r == nrows - 1 || c == 0 || c == ncols - 1) {
+
+		if (r == 0 && c == 0)
+		    asp_value = -7;
+		else if (r == 0 && c == ncols - 1)
+		    asp_value = -5;
+		else if (r == nrows - 1 && c == 0)
+		    asp_value = -1;
+		else if (r == nrows - 1 && c == ncols - 1)
+		    asp_value = -3;
+		else if (r == 0)
+		    asp_value = -2;
+		else if (c == 0)
+		    asp_value = -4;
+		else if (r == nrows - 1)
+		    asp_value = -6;
+		else if (c == ncols - 1)
+		    asp_value = -8;
+
+		seg_get(&watalt, (char *)&wa, r, c);
+		ele_value = wa.ele;
+		heap_add(r, c, ele_value);
+		FLAG_SET(flag_value, INLISTFLAG);
+		FLAG_SET(flag_value, EDGEFLAG);
+		bseg_put(&bitflags, &flag_value, r, c);
+		bseg_put(&asp, &asp_value, r, c);
+		continue;
+	    }
+
+	    /* any neighbour NULL ? */
+	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+		/* get r, c (r_nbr, c_nbr) for neighbours */
+		r_nbr = r + nextdr[ct_dir];
+		c_nbr = c + nextdc[ct_dir];
+
+		bseg_get(&bitflags, &flag_value_nbr, r_nbr, c_nbr);
+		is_null = FLAG_GET(flag_value_nbr, NULLFLAG);
+
+		if (is_null) {
+		    asp_value = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
+		    seg_get(&watalt, (char *)&wa, r, c);
+		    ele_value = wa.ele;
+		    heap_add(r, c, ele_value);
+		    FLAG_SET(flag_value, INLISTFLAG);
+		    FLAG_SET(flag_value, EDGEFLAG);
+		    bseg_put(&bitflags, &flag_value, r, c);
+		    bseg_put(&asp, &asp_value, r, c);
+
+		    break;
+		}
+	    }
+	    if (asp_value) /* some neighbour was NULL, point added to list */
+		continue;
+	    
+	    /* real depression ? */
+	    if (depr_fd >= 0) {
+		if (!Rast_is_c_null_value(&depr_buf[c]) && depr_buf[c] != 0) {
+		    seg_get(&watalt, (char *)&wa, r, c);
+		    ele_value = wa.ele;
+		    heap_add(r, c, ele_value);
+		    FLAG_SET(flag_value, INLISTFLAG);
+		    FLAG_SET(flag_value, DEPRFLAG);
+		    bseg_put(&bitflags, &flag_value, r, c);
+		    bseg_put(&asp, &asp_value, r, c);
+		    n_depr_cells++;
+		}
+	    }
+	}
+    }
+    G_percent(nrows, nrows, 2);	/* finish it */
+
+    if (depr_fd >= 0) {
+	Rast_close(depr_fd);
+	G_free(depr_buf);
+    }
+
+    G_debug(1, "%lld edge cells", heap_size - n_depr_cells);
+    if (n_depr_cells)
+	G_debug(1, "%lld cells in depressions", n_depr_cells);
+
+    return 1;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/load.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/load.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/load.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,168 @@
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+/* need elevation map, do A* search on elevation like for r.watershed */
+
+int ele_round(double x)
+{
+    if (x >= 0.0)
+	return x + .5;
+    else
+	return x - .5;
+}
+
+/*
+ * loads elevation and optional flow accumulation map to memory and
+ * gets start points for A* Search
+ * start points are edges
+ */
+int load_maps(int ele_fd, int acc_fd)
+{
+    int r, c;
+    void *ele_buf, *ptr, *acc_buf = NULL, *acc_ptr = NULL;
+    CELL ele_value, *stream_id;
+    DCELL dvalue, acc_value;
+    size_t ele_size, acc_size = 0;
+    int ele_map_type, acc_map_type = 0;
+    WAT_ALT *wabuf;
+    char *flag_value_buf, *aspect;
+
+    if (acc_fd < 0)
+	G_message(_("Loading elevation map..."));
+    else
+	G_message(_("Loading input maps..."));
+
+    n_search_points = n_points = 0;
+
+    G_debug(1, "get buffers");
+    ele_map_type = Rast_get_map_type(ele_fd);
+    ele_size = Rast_cell_size(ele_map_type);
+    ele_buf = Rast_allocate_buf(ele_map_type);
+
+    if (ele_buf == NULL) {
+	G_warning(_("Could not allocate memory"));
+	return -1;
+    }
+
+    if (acc_fd >= 0) {
+	acc_map_type = Rast_get_map_type(acc_fd);
+	acc_size = Rast_cell_size(acc_map_type);
+	acc_buf = Rast_allocate_buf(acc_map_type);
+	if (acc_buf == NULL) {
+	    G_warning(_("Could not allocate memory"));
+	    return -1;
+	}
+    }
+
+    ele_scale = 1;
+    if (ele_map_type == FCELL_TYPE || ele_map_type == DCELL_TYPE)
+	ele_scale = 1000;	/* should be enough to do the trick */
+
+    wabuf = G_malloc(ncols * sizeof(WAT_ALT));
+    flag_value_buf = G_malloc(ncols * sizeof(char));
+    stream_id = G_malloc(ncols * sizeof(CELL));
+    aspect = G_malloc(ncols * sizeof(char));
+
+    G_debug(1, "start loading %d rows, %d cols", nrows, ncols);
+    for (r = 0; r < nrows; r++) {
+
+	G_percent(r, nrows, 2);
+
+	Rast_get_row(ele_fd, ele_buf, r, ele_map_type);
+	ptr = ele_buf;
+
+	if (acc_fd >= 0) {
+	    Rast_get_row(acc_fd, acc_buf, r, acc_map_type);
+	    acc_ptr = acc_buf;
+	}
+
+	for (c = 0; c < ncols; c++) {
+
+	    flag_value_buf[c] = 0;
+	    aspect[c] = 0;
+	    stream_id[c] = 0;
+
+	    /* check for masked and NULL cells */
+	    if (Rast_is_null_value(ptr, ele_map_type)) {
+		FLAG_SET(flag_value_buf[c], NULLFLAG);
+		FLAG_SET(flag_value_buf[c], INLISTFLAG);
+		FLAG_SET(flag_value_buf[c], WORKEDFLAG);
+		FLAG_SET(flag_value_buf[c], WORKED2FLAG);
+		Rast_set_c_null_value(&ele_value, 1);
+		/* flow accumulation */
+		if (acc_fd >= 0) {
+		    if (!Rast_is_null_value(acc_ptr, acc_map_type))
+			G_fatal_error(_("Elevation map is NULL but accumulation map is not NULL!"));
+		}
+		Rast_set_d_null_value(&acc_value, 1);
+	    }
+	    else {
+		switch (ele_map_type) {
+		case CELL_TYPE:
+		    ele_value = *((CELL *) ptr);
+		    break;
+		case FCELL_TYPE:
+		    dvalue = *((FCELL *) ptr);
+		    dvalue *= ele_scale;
+		    ele_value = ele_round(dvalue);
+		    break;
+		case DCELL_TYPE:
+		    dvalue = *((DCELL *) ptr);
+		    dvalue *= ele_scale;
+		    ele_value = ele_round(dvalue);
+		    break;
+		}
+		if (acc_fd < 0)
+		    acc_value = 1;
+		else {
+		    if (Rast_is_null_value(acc_ptr, acc_map_type)) {
+			/* can this be ok after weighing ? */
+			G_fatal_error(_("Accumulation map is NULL but elevation map is not NULL!"));
+		    }
+
+		    switch (acc_map_type) {
+		    case CELL_TYPE:
+			acc_value = *((CELL *) acc_ptr);
+			break;
+		    case FCELL_TYPE:
+			acc_value = *((FCELL *) acc_ptr);
+			break;
+		    case DCELL_TYPE:
+			acc_value = *((DCELL *) acc_ptr);
+			break;
+		    }
+		}
+
+		n_points++;
+	    }
+
+	    wabuf[c].wat = acc_value;
+	    wabuf[c].ele = ele_value;
+	    ptr = G_incr_void_ptr(ptr, ele_size);
+	    if (acc_fd >= 0)
+		acc_ptr = G_incr_void_ptr(acc_ptr, acc_size);
+	}
+	seg_put_row(&watalt, (char *) wabuf, r);
+	bseg_put_row(&asp, aspect, r);
+	cseg_put_row(&stream, stream_id, r);
+	bseg_put_row(&bitflags, flag_value_buf, r);
+    }
+    G_percent(nrows, nrows, 1);	/* finish it */
+
+    Rast_close(ele_fd);
+    G_free(ele_buf);
+    G_free(wabuf);
+    G_free(flag_value_buf);
+    G_free(stream_id);
+    G_free(aspect);
+
+    if (acc_fd >= 0) {
+	Rast_close(acc_fd);
+	G_free(acc_buf);
+    }
+    
+    G_debug(1, "%lld non-NULL cells", n_points);
+
+    return n_points;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/local_proto.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/local_proto.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/local_proto.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,89 @@
+
+#ifndef __LOCAL_PROTO_H__
+#define __LOCAL_PROTO_H__
+
+#include <grass/raster.h>
+#include "flag.h"
+#include "seg.h"
+
+#define GW_LARGE_INT off_t
+
+#define INDEX(r, c) ((r) * ncols + (c))
+#define MAXDEPTH 1000     /* maximum supported tree depth of stream network */
+
+#define POINT       struct a_point
+POINT {
+    int r, c;
+};
+
+#define HEAP_PNT    struct heap_point
+HEAP_PNT {
+   GW_LARGE_INT added;
+   CELL ele;
+   POINT pnt;
+};
+
+#define WAT_ALT    struct wat_altitude
+WAT_ALT {
+   CELL ele;
+   DCELL wat;
+};
+
+struct snode
+{
+    int r, c;
+    int id;
+    int n_trib;           /* number of tributaries */
+    int n_trib_total;     /* number of all upstream stream segments */
+    int n_alloc;          /* n allocated tributaries */
+    int *trib;
+};
+
+/* extern variables */
+extern struct snode *stream_node;
+extern int nrows, ncols;
+extern GW_LARGE_INT n_search_points, n_points, nxt_avail_pt;
+extern GW_LARGE_INT heap_size;
+extern unsigned int n_stream_nodes, n_alloc_nodes;
+extern POINT *outlets;
+extern unsigned int n_outlets, n_alloc_outlets;
+extern char drain[3][3];
+extern char sides;
+extern int c_fac;
+extern int ele_scale;
+extern int have_depressions;
+
+extern SSEG search_heap;
+extern SSEG astar_pts;
+extern BSEG bitflags;
+extern SSEG watalt;
+extern BSEG asp;
+extern CSEG stream;
+
+/* load.c */
+int load_maps(int, int);
+
+/* init_search.c */
+int init_search(int);
+
+/* do_astar.c */
+int do_astar(void);
+GW_LARGE_INT heap_add(int, int, CELL);
+
+/* streams.c */
+int do_accum(double);
+int extract_streams(double, double, int, int);
+
+/* thin.c */
+int thin_streams(void);
+
+/* basins.c */
+int basin_borders(void);
+
+/* del_streams.c */
+int del_streams(int);
+
+/* close.c */
+int close_maps(char *, char *, char *);
+
+#endif /* __LOCAL_PROTO_H__ */

Added: grass-addons/grass7/grass7/raster/r.stream.extract/main.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/main.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/main.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,442 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.stream.extract
+ * AUTHOR(S):    Markus Metz <markus.metz.giswork gmail.com>
+ * PURPOSE:      Hydrological analysis
+ *               Extracts stream networks from accumulation raster with
+ *               given threshold
+ * COPYRIGHT:    (C) 1999-2009 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+/* global variables */
+struct snode *stream_node;
+int nrows, ncols;
+GW_LARGE_INT n_search_points, n_points, nxt_avail_pt;
+GW_LARGE_INT heap_size;
+unsigned int n_stream_nodes, n_alloc_nodes;
+POINT *outlets;
+unsigned int n_outlets, n_alloc_outlets;
+char drain[3][3] = { {7, 6, 5}, {8, 0, 4}, {1, 2, 3} };
+char sides;
+int c_fac;
+int ele_scale;
+int have_depressions;
+
+SSEG search_heap;
+SSEG astar_pts;
+BSEG bitflags;
+SSEG watalt;
+BSEG asp;
+CSEG stream;
+
+CELL *astar_order;
+
+int main(int argc, char *argv[])
+{
+    struct
+    {
+	struct Option *ele, *acc, *depression;
+	struct Option *threshold, *d8cut;
+	struct Option *mont_exp;
+	struct Option *min_stream_length;
+	struct Option *memory;
+    } input;
+    struct
+    {
+	struct Option *stream_rast;
+	struct Option *stream_vect;
+	struct Option *dir_rast;
+    } output;
+    struct GModule *module;
+    int ele_fd, acc_fd, depr_fd;
+    double threshold, d8cut, mont_exp;
+    int min_stream_length = 0, memory;
+    int seg_cols, seg_rows;
+    double seg2kb;
+    int num_open_segs, num_open_array_segs, num_seg_total;
+    double memory_divisor, heap_mem, disk_space;
+    const char *mapset;
+
+    G_gisinit(argv[0]);
+
+    /* Set description */
+    module = G_define_module();
+    G_add_keyword(_("raster"));
+    G_add_keyword(_("hydrology"));
+    module->description = _("Stream network extraction");
+
+    input.ele = G_define_standard_option(G_OPT_R_INPUT);
+    input.ele->key = "elevation";
+    input.ele->label = _("Elevation map");
+    input.ele->description = _("Elevation on which entire analysis is based");
+
+    input.acc = G_define_standard_option(G_OPT_R_INPUT);
+    input.acc->key = "accumulation";
+    input.acc->label = _("Accumulation map");
+    input.acc->required = NO;
+    input.acc->description =
+	_("Stream extraction will use provided accumulation instead of calculating it anew");
+
+    input.depression = G_define_standard_option(G_OPT_R_INPUT);
+    input.depression->key = "depression";
+    input.depression->label = _("Map with real depressions");
+    input.depression->required = NO;
+    input.depression->description =
+	_("Streams will not be routed out of real depressions");
+
+    input.threshold = G_define_option();
+    input.threshold->key = "threshold";
+    input.threshold->label = _("Minimum flow accumulation for streams");
+    input.threshold->description = _("Must be > 0");
+    input.threshold->required = YES;
+    input.threshold->type = TYPE_DOUBLE;
+
+    input.d8cut = G_define_option();
+    input.d8cut->key = "d8cut";
+    input.d8cut->label = _("Use SFD above this threshold");
+    input.d8cut->description =
+	_("If accumulation is larger than d8cut, SFD is used instead of MFD."
+	  " Applies only if no accumulation map is given.");
+    input.d8cut->required = NO;
+    input.d8cut->answer = "infinity";
+    input.d8cut->type = TYPE_DOUBLE;
+
+    input.mont_exp = G_define_option();
+    input.mont_exp->key = "mexp";
+    input.mont_exp->type = TYPE_DOUBLE;
+    input.mont_exp->required = NO;
+    input.mont_exp->answer = "0";
+    input.mont_exp->label =
+	_("Montgomery exponent for slope, disabled with 0");
+    input.mont_exp->description =
+	_("Montgomery: accumulation is multiplied with pow(slope,mexp) and then compared with threshold.");
+
+    input.min_stream_length = G_define_option();
+    input.min_stream_length->key = "stream_length";
+    input.min_stream_length->type = TYPE_INTEGER;
+    input.min_stream_length->required = NO;
+    input.min_stream_length->answer = "0";
+    input.min_stream_length->label =
+	_("Delete stream segments shorter than stream_length cells.");
+    input.min_stream_length->description =
+	_("Applies only to first-order stream segments (springs/stream heads).");
+
+    input.memory = G_define_option();
+    input.memory->key = "memory";
+    input.memory->type = TYPE_INTEGER;
+    input.memory->required = NO;
+    input.memory->answer = "300";
+    input.memory->description = _("Maximum memory to be used in MB");
+
+    output.stream_rast = G_define_standard_option(G_OPT_R_OUTPUT);
+    output.stream_rast->key = "stream_rast";
+    output.stream_rast->description =
+	_("Output raster map with unique stream ids");
+    output.stream_rast->required = NO;
+    output.stream_rast->guisection = _("Output options");
+
+    output.stream_vect = G_define_standard_option(G_OPT_V_OUTPUT);
+    output.stream_vect->key = "stream_vect";
+    output.stream_vect->description =
+	_("Output vector with unique stream ids");
+    output.stream_vect->required = NO;
+    output.stream_vect->guisection = _("Output options");
+
+    output.dir_rast = G_define_standard_option(G_OPT_R_OUTPUT);
+    output.dir_rast->key = "direction";
+    output.dir_rast->description =
+	_("Output raster map with flow direction");
+    output.dir_rast->required = NO;
+    output.dir_rast->guisection = _("Output options");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    /***********************/
+    /*    check options    */
+    /***********************/
+
+    /* input maps exist ? */
+    if (!G_find_raster(input.ele->answer, ""))
+	G_fatal_error(_("Raster map <%s> not found"), input.ele->answer);
+
+    if (input.acc->answer) {
+	if (!G_find_raster(input.acc->answer, ""))
+	    G_fatal_error(_("Raster map <%s> not found"), input.acc->answer);
+    }
+
+    if (input.depression->answer) {
+	if (!G_find_raster(input.depression->answer, ""))
+	    G_fatal_error(_("Raster map <%s> not found"), input.depression->answer);
+	have_depressions = 1;
+    }
+    else
+	have_depressions = 0;
+
+    /* threshold makes sense */
+    threshold = atof(input.threshold->answer);
+    if (threshold <= 0)
+	G_fatal_error(_("Threshold must be > 0 but is %f"), threshold);
+
+    /* d8cut */
+    if (strcmp(input.d8cut->answer, "infinity") == 0) {
+	d8cut = DBL_MAX;
+    }
+    else {
+	d8cut = atof(input.d8cut->answer);
+	if (d8cut < 0)
+	    G_fatal_error(_("d8cut must be positive or zero but is %f"),
+			  d8cut);
+    }
+
+    /* Montgomery stream initiation */
+    if (input.mont_exp->answer) {
+	mont_exp = atof(input.mont_exp->answer);
+	if (mont_exp < 0)
+	    G_fatal_error(_("Montgomery exponent must be positive or zero but is %f"),
+			  mont_exp);
+	if (mont_exp > 3)
+	    G_warning(_("Montgomery exponent is %f, recommended range is 0.0 - 3.0"),
+		      mont_exp);
+    }
+    else
+	mont_exp = 0;
+
+    /* Minimum stream segment length */
+    if (input.min_stream_length->answer) {
+	min_stream_length = atoi(input.min_stream_length->answer);
+	if (min_stream_length < 0)
+	    G_fatal_error(_("Minimum stream length must be positive or zero but is %d"),
+			  min_stream_length);
+    }
+    else
+	min_stream_length = 0;
+	
+    if (input.memory->answer) {
+	memory = atoi(input.memory->answer);
+	if (memory <= 0)
+	    G_fatal_error(_("Memory must be positive but is %d"),
+			  memory);
+    }
+    else
+	memory = 300;
+
+    /* Check for some output map */
+    if ((output.stream_rast->answer == NULL)
+	&& (output.stream_vect->answer == NULL)
+	&& (output.dir_rast->answer == NULL)) {
+	G_fatal_error(_("Sorry, you must choose at least one output map."));
+    }
+
+    /*********************/
+    /*    preparation    */
+    /*********************/
+
+    /* open input maps */
+    mapset = G_find_raster2(input.ele->answer, "");
+    ele_fd = Rast_open_old(input.ele->answer, mapset);
+    if (ele_fd < 0)
+	G_fatal_error(_("Could not open input map %s"), input.ele->answer);
+
+    if (input.acc->answer) {
+	mapset = G_find_raster2(input.acc->answer, "");
+	acc_fd = Rast_open_old(input.acc->answer, mapset);
+	if (acc_fd < 0)
+	    G_fatal_error(_("Could not open input map %s"),
+			  input.acc->answer);
+    }
+    else
+	acc_fd = -1;
+
+    if (input.depression->answer) {
+	mapset = G_find_raster2(input.depression->answer, "");
+	depr_fd = Rast_open_old(input.depression->answer, mapset);
+	if (depr_fd < 0)
+	    G_fatal_error(_("Could not open input map %s"),
+			  input.depression->answer);
+    }
+    else
+	depr_fd = -1;
+
+    /* set global variables */
+    nrows = Rast_window_rows();
+    ncols = Rast_window_cols();
+    sides = 8;	/* not a user option */
+    c_fac = 5;	/* not a user option, MFD covergence factor 5 gives best results */
+
+    /* segment structures */
+    seg_rows = seg_cols = 64;
+    seg2kb = seg_rows * seg_cols / 1024.;
+
+    /* balance segment files */
+    /* elevation + accumulation: * 2 */
+    memory_divisor = sizeof(WAT_ALT) * 2;
+    disk_space = sizeof(WAT_ALT);
+    /* aspect: as is */
+    memory_divisor += sizeof(char);
+    disk_space += sizeof(char);
+    /* stream ids: / 2 */
+    memory_divisor += sizeof(int) / 2.;
+    disk_space += sizeof(int);
+    /* flags: * 4 */
+    memory_divisor += sizeof(char) * 4;
+    disk_space += sizeof(char);
+    /* astar_points: / 16 */
+    /* ideally only a few but large segments */
+    memory_divisor += sizeof(POINT) / 16.;
+    disk_space += sizeof(POINT);
+    /* heap points: / 4 */
+    memory_divisor += sizeof(HEAP_PNT) / 4.;
+    disk_space += sizeof(HEAP_PNT);
+    
+    /* KB -> MB */
+    memory_divisor *= seg2kb / 1024.;
+    disk_space *= seg2kb / 1024.;
+
+    num_open_segs = memory / memory_divisor;
+    heap_mem = num_open_segs * seg2kb * sizeof(HEAP_PNT) /
+               (4. * 1024.);
+    num_seg_total = (ncols / seg_cols + 1) * (nrows / seg_rows + 1);
+    if (num_open_segs > num_seg_total) {
+	heap_mem += (num_open_segs - num_seg_total) * memory_divisor;
+	heap_mem -= (num_open_segs - num_seg_total) * seg2kb *
+		    sizeof(HEAP_PNT) / (4. * 1024.);
+	num_open_segs = num_seg_total;
+    }
+    if (num_open_segs < 16) {
+	num_open_segs = 16;
+	heap_mem = num_open_segs * seg2kb * sizeof(HEAP_PNT) /
+	           (4. * 1024.);
+    }
+    G_verbose_message(_("%.2f%% of data are kept in memory"),
+                      100. * num_open_segs / num_seg_total);
+    disk_space *= num_seg_total;
+    if (disk_space < 1024.0)
+	G_verbose_message(_("Will need up to %.2f MB of disk space"), disk_space);
+    else
+	G_verbose_message(_("Will need up to %.2f GB (%.0f MB) of disk space"),
+	           disk_space / 1024.0, disk_space);
+
+    /* open segment files */
+    G_verbose_message(_("Creating temporary files..."));
+    seg_open(&watalt, nrows, ncols, seg_rows, seg_cols, num_open_segs * 2,
+        sizeof(WAT_ALT), 1);
+    if (num_open_segs * 2 > num_seg_total)
+	heap_mem += (num_open_segs * 2 - num_seg_total) * seg2kb *
+	            sizeof(WAT_ALT) / 1024.;
+    cseg_open(&stream, seg_rows, seg_cols, num_open_segs / 2.);
+    bseg_open(&asp, seg_rows, seg_cols, num_open_segs);
+    bseg_open(&bitflags, seg_rows, seg_cols, num_open_segs * 4);
+    if (num_open_segs * 4 > num_seg_total)
+	heap_mem += (num_open_segs * 4 - num_seg_total) * seg2kb / 1024.;
+
+    /* load maps */
+    if (load_maps(ele_fd, acc_fd) < 0)
+	G_fatal_error(_("Could not load input map(s)"));
+    else if (!n_points)
+	G_fatal_error(_("No non-NULL cells in input map(s)"));
+
+    G_debug(1, "open segments for A* points");
+    /* columns per segment */
+    seg_cols = seg_rows * seg_rows;
+    num_seg_total = n_points / seg_cols;
+    if (n_points % seg_cols > 0)
+	num_seg_total++;
+    /* no need to have more segments open than exist */
+    num_open_array_segs = num_open_segs / 16.;
+    if (num_open_array_segs > num_seg_total)
+	num_open_array_segs = num_seg_total;
+    if (num_open_array_segs < 1)
+	num_open_array_segs = 1;
+    
+    G_debug(1, "segment size for A* points: %d", seg_cols);
+    seg_open(&astar_pts, 1, n_points, 1, seg_cols, num_open_array_segs,
+	     sizeof(POINT), 1);
+
+    /* one-based d-ary search_heap with astar_pts */
+    G_debug(1, "open segments for A* search heap");
+	
+    /* allowed memory for search heap in MB */
+    G_debug(1, "heap memory %.2f MB", heap_mem);
+    /* columns per segment */
+    /* larger is faster */
+    seg_cols = seg_rows * seg_rows * seg_rows;
+    num_seg_total = n_points / seg_cols;
+    if (n_points % seg_cols > 0)
+	num_seg_total++;
+    /* no need to have more segments open than exist */
+    num_open_array_segs = (1 << 20) * heap_mem / (seg_cols * sizeof(HEAP_PNT));
+    if (num_open_array_segs > num_seg_total)
+	num_open_array_segs = num_seg_total;
+    if (num_open_array_segs < 2)
+	num_open_array_segs = 2;
+
+    G_debug(1, "A* search heap open segments %d, total %d",
+            num_open_array_segs, num_seg_total);
+    G_debug(1, "segment size for heap points: %d", seg_cols);
+    /* the search heap will not hold more than 5% of all points at any given time ? */
+    /* chances are good that the heap will fit into one large segment */
+    seg_open(&search_heap, 1, n_points + 1, 1, seg_cols,
+	     num_open_array_segs, sizeof(HEAP_PNT), 1);
+
+    /********************/
+    /*    processing    */
+    /********************/
+
+    /* initialize A* search */
+    if (init_search(depr_fd) < 0)
+	G_fatal_error(_("Could not initialize search"));
+
+    /* sort elevation and get initial stream direction */
+    if (do_astar() < 0)
+	G_fatal_error(_("Could not sort elevation map"));
+    seg_close(&search_heap);
+
+    if (acc_fd < 0) {
+	/* accumulate surface flow */
+	if (do_accum(d8cut) < 0)
+	    G_fatal_error(_("Could not calculate flow accumulation"));
+    }
+
+    /* extract streams */
+    if (extract_streams
+	(threshold, mont_exp, min_stream_length, acc_fd < 0) < 0)
+	G_fatal_error(_("Could not extract streams"));
+
+    seg_close(&astar_pts);
+    seg_close(&watalt);
+
+    /* thin streams */
+    if (thin_streams() < 0)
+	G_fatal_error(_("Could not thin streams"));
+
+    /* delete short streams */
+    if (min_stream_length) {
+	if (del_streams(min_stream_length) < 0)
+	    G_fatal_error(_("Could not delete short stream segments"));
+    }
+
+    /* write output maps */
+    if (close_maps(output.stream_rast->answer, output.stream_vect->answer,
+		   output.dir_rast->answer) < 0)
+	G_fatal_error(_("Could not write output maps"));
+
+    bseg_close(&asp);
+    cseg_close(&stream);
+    bseg_close(&bitflags);
+
+    exit(EXIT_SUCCESS);
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/r.stream.extract.html
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/r.stream.extract.html	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/r.stream.extract.html	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,239 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.stream.extract</em> extracts streams in both raster and vector
+format from a required input <em>elevation</em> map and optional input
+<em>accumulation map</em>.
+
+<h2>OPTIONS</h2>
+
+<dl>
+<dt><em>elevation</em> 
+<dd>Input map, required: Elevation on which entire analysis is based.
+NULL (nodata) cells are ignored, zero and negative values are valid
+elevation data. Gaps in the elevation map that are located within the
+area of interest must be filled beforehand, e.g. with
+<em>r.fillnulls</em>, to avoid distortions.
+<p>
+<dt><em>accumulation</em>
+<dd>Input map, optional: Accumulation values of the provided
+<em>accumulation</em> map are used and not calculated from the input
+<em>elevation</em> map. If <em>accumulation</em> is given,
+<em>elevation</em> must be exactly the same map used to calculate
+<em>accumulation</em>. If <em>accumulation</em> was calculated with
+<a href="r.terraflow.html">r.terraflow</a>, the filled elevation output
+of r.terraflow must be used. Further on, the current region should be 
+aligned to the <em>accumulation map</em>. Flow direction is
+first calculated from <em>elevation</em> and then adjusted to
+<em>accumulation</em>. It is not necessary to provide <em>accumulation</em>
+as the number of cells, it can also be the optionally adjusted or
+weighed total contributing area in square meters or any other unit. 
+When an original flow accumulation map is adjusted or weighed, the 
+adjustment or weighing should not convert valid accumulation values to 
+NULL (nodata) values.
+<p>
+<dt><em>depression</em> 
+<dd>Input map, optional: All non-NULL and non-zero cells will be regarded
+as real depressions. Streams will not be routed out of depressions. If an
+area is marked as depression but the elevation model has no depression
+at this location, streams will not stop there. If a flow accumulation map
+and a map with real depressions are provided, the flow accumulation map
+must match the depression map such that flow is not distributed out of 
+the indicated depressions. It is recommended to use internally computed
+flow accumulation if a depression map is provided.
+<p>
+<dt><em>threshold</em>
+<dd>Required: <em>threshold</em> for stream initiation by overland flow:
+the minumum (optionally modifed) flow accumulation value that will initiate
+a new stream. If Montgomery's method for channel initiation is used, the
+cell value of the accumulation input map is multiplied by
+(tan(local slope))<sup>mexp</sup> and then compared to <em>threshold</em>.
+<p>
+<dt><em>d8cut</em>
+<dd>Minimum amount of overland flow (accumulation) when SFD (D8) will be
+used instead of MFD (FD8) to calculate flow accumulation. Only applies
+if no accumulation map is provided. Setting to 0 disables MFD completely.
+<p>
+<dt><em>mexp</em>
+<dd>Use the method of Montgomery and Foufoula-Georgiou (1993) to
+initiate a stream with exponent <em>mexp</em>. The cell value of the
+accumulation input map is multiplied by (tan(local slope))<sup>mexp</sup>
+and then compared to <em>threshold</em>. If threshold is reached or
+exceeded, a new stream is initiated. The default value 0 disables
+Montgomery. Montgomery and Foufoula-Georgiou (1993) generally recommend
+to use 2.0 as exponent. <em>mexp</em> values closer to 0 will produce
+streams more similar to streams extracted with Montgomery disabled.
+Larger <em>mexp</em> values decrease the number of streams in flat areas
+and increase the number of streams in steep areas. If <em>weight</em> is
+given, the weight is applied first.
+<p>
+<dt><em>stream_length</em>
+<dd>Minimum stream length in number of cells for first-order (head/spring)
+stream segments. All first-order stream segments shorter than
+<em>stream_length</em> will be deleted.
+
+<p>
+<dt><em>stream_rast</em>
+<dd>Output raster map with extracted streams. Cell values encode unique
+ID for each stream segment.
+<p>
+<dt><em>stream_vect</em>
+<dd>Output vector map with extracted stream segments and points. Points
+are written at the start location of each stream segment and at the
+outlet of a stream network. In layer 1, categories are unique IDs,
+identical to the cell value of the raster output. The attribute table
+for layer 1 holds information about the type of stream segment: start
+segment, or intermediate segment with tributaries. Columns are cat int,
+stream_type varchar(), type_code int. The encoding for type_code is 0 =
+start, 1 = intermediate. In layer 2, categories are identical to
+type_code in layer 1 with additional category 2 = outlet for outlet
+points. Points with category 1 = intermediate in layer 2 are at the
+location of confluences.
+<p>
+<dt><em>direction</em>
+<dd>Output raster map with flow direction for all non-NULL cells in
+input elevation. Flow direction is of D8 type with a range of 1 to 8.
+Multiplying values with 45 gives degrees CCW from East. Flow direction
+was adjusted during thinning, taking shortcuts and skipping cells that
+were eliminated by the thinning procedure.
+</dl>
+
+<h2>NOTES</h2>
+
+<h4>Stream extraction</h4>
+If no accumulation input map is provided, flow accumulation is
+determined with a hydrological anaylsis similar to
+<a href="r.watershed.html">r.watershed</a>. The algorithm is
+MFD (FD8) after Holmgren 1994, as for
+<a href="r.watershed.html">r.watershed</a>. The <em>threshold</em>
+option determines the number of streams and detail of stream networks.
+Whenever flow accumulation reaches <em>threshold</em>, a new stream is
+started and traced downstream to its outlet point. As for
+<a href="r.watershed.html">r.watershed</a>, flow accumulation is
+calculated as the number of cells draining through a cell.
+
+<h4>Weighed flow accumulation</h4>
+Flow accumulation can be calculated first, e.g. with
+<a href="r.watershed.html">r.watershed</a>, and then modified before
+using it as input for <em>r.stream.extract</em>. In its general form, a
+weighed accumulation map is generated by first creating a weighing map
+and then multiplying the accumulation map with the weighing map using
+<a href="r.mapcalc.html">r.mapcalc</a>. It is highly recommended to
+evaluate the weighed flow accumulation map first, before using it as
+input for <em>r.stream.extract</em>.
+<p>
+This allows e.g. to decrease the number of streams in dry areas and
+increase the number of streams in wet areas by setting <em>weight</em>
+to smaller than 1 in dry areas and larger than 1 in wet areas.
+<p>
+Another possibility is to restrict channel initiation to valleys
+determined from terrain morphology. Valleys can be determined with
+<a href="r.param.scale.html">r.param.scale</a> param=crosc
+(cross-sectional or tangential curvature). Curvature values < 0
+indicate concave features, i.e. valleys. The size of the processing
+window determines whether narrow or broad valleys will be identified
+(See example below).
+
+<h4>Defining a region of interest</h4>
+The stream extraction procedure can be restricted to a certain region of 
+interest, e.g. a subbasin, by setting the computational region with 
+<em>g.region</em> and/or creating a MASK. Such region of interest should 
+be a complete catchment area, complete in the sense that the complete 
+area upstream of an outlet point is included and buffered with at least 
+one cell.
+
+<h4>Stream output</h4>
+The <em>stream_rast</em> output raster and vector contains stream
+segments with unique IDs. Note that these IDs are different from the IDs
+assigned by <a href="r.watershed.html">r.watershed</a>. The vector
+output also contains points at the location of the start of a stream
+segment, at confluences and at stream network outlet locations.
+<p>
+
+<h2>EXAMPLE</h2>
+This example is based on the elevation map <em>elevation.10m</em> in the
+sample dataset spearfish60 and uses valleys determined with
+<a href="r.param.scale.html">r.param.scale</a> to weigh an accumulation
+map produced with <a href="r.watershed.html">r.watershed</a>.
+
+<pre>
+# set region
+g.region -p rast=elevation.10m at PERMANENT
+
+# calculate flow accumulation
+r.watershed ele=elevation.10m at PERMANENT acc=elevation.10m.acc -f
+
+# curvature to get narrow valleys
+r.param.scale input="elevation.10m at PERMANENT" output="tangential_curv_5" size=5 param=crosc
+
+# curvature to get a bit broader valleys
+r.param.scale input="elevation.10m at PERMANENT" output="tangential_curv_7" size=7 param=crosc
+
+# curvature to get broad valleys
+r.param.scale input="elevation.10m at PERMANENT" output="tangential_curv_11" size=11 param=crosc
+
+# create weight map
+r.mapcalc "weight = if(tangential_curv_5 < 0, -100 * tangential_curv_5, \
+                    if(tangential_curv_7 < 0, -100 * tangential_curv_7, \
+		    if(tangential_curv_11 < 0, -100 * tangential_curv_11, 0.000001)))"
+
+# weigh accumulation map
+r.mapcalc "elevation.10m.acc.weighed = elevation.10m.acc * weight"
+
+# copy color table from original accumulation map
+r.colors map=elevation.10m.acc.weighed raster=elevation.10m.acc
+</pre>
+
+Display both the original and the weighed accumulation map.
+<br>
+Compare them and proceed if the weighed accumulation map makes sense.
+
+<pre>
+# extract streams
+r.stream.extract elevation=elevation.10m at PERMANENT \
+                 accumulation=elevation.10m.acc.weighed \
+		 threshold=1000 \
+		 stream_rast=elevation.10m.streams
+
+# extract streams using the original accumulation map
+r.stream.extract elevation=elevation.10m at PERMANENT \
+                 accumulation=elevation.10m.acc \
+		 threshold=1000 \
+		 stream_rast=elevation.10m.streams.noweight
+</pre>
+
+Now display both stream maps and decide which one is more realistic.
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.watershed.html">r.watershed</a>,
+<a href="r.terraflow.html">r.terraflow</a>,
+<a href="r.param.scale.html">r.param.scale</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>,
+<a href="r.thin.html">r.thin</a>,
+<a href="r.to.vect.html">r.to.vect</a>
+</em>
+
+<h2>REFERENCES</h2>
+Ehlschlaeger, C. (1989). <i>Using the A<sup>T</sup> Search Algorithm
+to Develop Hydrologic Models from Digital Elevation Data</i>,
+<b>Proceedings of International Geographic Information Systems (IGIS)
+Symposium '89</b>, pp 275-281 (Baltimore, MD, 18-19 March 1989).<br>
+URL: <a href="http://faculty.wiu.edu/CR-Ehlschlaeger2/older/IGIS/paper.html">
+http://faculty.wiu.edu/CR-Ehlschlaeger2/older/IGIS/paper.html</a>
+
+<p>
+Holmgren, P. (1994). <i>Multiple flow direction algorithms for runoff 
+modelling in grid based elevation models: An empirical evaluation.</i>
+<b>Hydrological Processes</b> Vol 8(4), pp 327-334.<br>
+DOI: <a href="http://dx.doi.org/10.1002/hyp.3360080405">10.1002/hyp.3360080405</a>
+
+<p>
+Montgomery, D.R., Foufoula-Georgiou, E. (1993). <i>Channel network source
+representation using digital elevation models.</i>
+<b>Water Resources Research</b> Vol 29(12), pp 3925-3934. 
+
+<h2>AUTHOR</h2>
+Markus Metz
+
+<p><i>Last changed: $Date: 2012-04-09 21:11:44 +0200 (Mon, 09 Apr 2012) $</i>

Added: grass-addons/grass7/grass7/raster/r.stream.extract/seg.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/seg.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/seg.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,112 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/glocale.h>
+#include "seg.h"
+
+int
+seg_open(SSEG *sseg, int nrows, int ncols, int row_in_seg, int col_in_seg,
+	 int nsegs_in_memory, int size_struct, int fill)
+{
+    char *filename;
+    int errflag;
+    int fd;
+
+    sseg->filename = NULL;
+    sseg->fd = -1;
+
+    filename = G_tempfile();
+    if (-1 == (fd = creat(filename, 0666))) {
+	G_warning(_("seg_open(): unable to create segment file"));
+	return -2;
+    }
+    if (fill)
+	errflag = segment_format(fd, nrows, ncols, row_in_seg,
+	                         col_in_seg, size_struct);
+    else
+	errflag = segment_format_nofill(fd, nrows, ncols, row_in_seg,
+	                         col_in_seg, size_struct);
+
+    if (0 > errflag) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("seg_open(): could not write segment file"));
+	    return -1;
+	}
+	else {
+	    G_warning(_("seg_open(): illegal configuration parameter(s)"));
+	    return -3;
+	}
+    }
+    close(fd);
+    if (-1 == (fd = open(filename, 2))) {
+	unlink(filename);
+	G_warning(_("seg_open(): unable to re-open segment file"));
+	return -4;
+    }
+    if (0 > (errflag = segment_init(&(sseg->seg), fd, nsegs_in_memory))) {
+	close(fd);
+	unlink(filename);
+	if (errflag == -1) {
+	    G_warning(_("seg_open(): could not read segment file"));
+	    return -5;
+	}
+	else {
+	    G_warning(_("seg_open(): out of memory"));
+	    return -6;
+	}
+    }
+    sseg->filename = filename;
+    sseg->fd = fd;
+    return 0;
+}
+
+int seg_close(SSEG *sseg)
+{
+    segment_release(&(sseg->seg));
+    close(sseg->fd);
+    unlink(sseg->filename);
+    return 0;
+}
+
+int seg_put(SSEG *sseg, char *value, int row, int col)
+{
+    if (segment_put(&(sseg->seg), value, row, col) < 0) {
+	G_warning(_("seg_put(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_put_row(SSEG *sseg, char *value, int row)
+{
+    if (segment_put_row(&(sseg->seg), value, row) < 0) {
+	G_warning(_("seg_put_row(): could not write segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_get(SSEG *sseg, char *value, int row, int col)
+{
+    if (segment_get(&(sseg->seg), value, row, col) < 0) {
+	G_warning(_("seg_get(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_get_row(SSEG *sseg, char *value, int row)
+{
+    if (segment_get_row(&(sseg->seg), value, row) < 0) {
+	G_warning(_("seg_get_row(): could not read segment file"));
+	return -1;
+    }
+    return 0;
+}
+
+int seg_flush(SSEG *sseg)
+{
+    segment_flush(&(sseg->seg));
+    return 0;
+}

Added: grass-addons/grass7/grass7/raster/r.stream.extract/seg.h
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/seg.h	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/seg.h	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,78 @@
+#ifndef __SEG_H__
+#define __SEG_H__
+
+#include <grass/raster.h>
+#include <grass/segment.h>
+
+#define CSEG struct _c_s_e_g_
+CSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+    char *name;			/* raster map read into segment file */
+    char *mapset;
+};
+
+#define DSEG struct _d_s_e_g_
+DSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+    char *name;			/* raster map read into segment file */
+    char *mapset;
+};
+
+#define BSEG struct _b_s_e_g_
+BSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+    char *name;			/* raster map read into segment file */
+    char *mapset;
+};
+
+#define SSEG struct _s_s_e_g_
+SSEG {
+    SEGMENT seg;		/* segment structure */
+    int fd;			/* fd for reading/writing segment file */
+    char *filename;		/* name of segment file */
+};
+
+/* bseg.c */
+int bseg_close(BSEG *);
+int bseg_get(BSEG *, char *, int, int);
+int bseg_open(BSEG *, int, int, int);
+int bseg_put(BSEG *, char *, int, int);
+int bseg_put_row(BSEG *, char *, int);
+int bseg_read_raster(BSEG *, char *, char *);
+int bseg_write_raster(BSEG *, char *);
+
+/* cseg.c */
+int cseg_close(CSEG *);
+int cseg_get(CSEG *, CELL *, int, int);
+int cseg_open(CSEG *, int, int, int);
+int cseg_put(CSEG *, CELL *, int, int);
+int cseg_put_row(CSEG *, CELL *, int);
+int cseg_read_raster(CSEG *, char *, char *);
+int cseg_write_raster(CSEG *, char *);
+
+/* dseg.c */
+int dseg_close(DSEG *);
+int dseg_get(DSEG *, double *, int, int);
+int dseg_open(DSEG *, int, int, int);
+int dseg_put(DSEG *, double *, int, int);
+int dseg_put_row(DSEG *, double *, int);
+int dseg_read_raster(DSEG *, char *, char *);
+int dseg_write_raster(DSEG *, char *);
+
+/* seg.c */
+int seg_close(SSEG *);
+int seg_get(SSEG *, char *, int, int);
+int seg_open(SSEG *, int, int, int, int, int, int, int);
+int seg_put(SSEG *, char *, int, int);
+int seg_put_row(SSEG *, char *, int);
+int seg_get(SSEG *, char *, int, int);
+int seg_get_row(SSEG *, char *, int);
+int seg_flush(SSEG *);
+
+#endif /* __SEG_H__ */

Added: grass-addons/grass7/grass7/raster/r.stream.extract/streams.c
===================================================================
--- grass-addons/grass7/grass7/raster/r.stream.extract/streams.c	                        (rev 0)
+++ grass-addons/grass7/grass7/raster/r.stream.extract/streams.c	2012-10-15 18:25:43 UTC (rev 53410)
@@ -0,0 +1,730 @@
+#include <stdlib.h>
+#include <math.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+double mfd_pow(double base)
+{
+    int i;
+    double result = base;
+
+    for (i = 2; i <= c_fac; i++) {
+	result *= base;
+    }
+    return result;
+}
+
+int continue_stream(CELL stream_id, int r, int c, int r_max, int c_max,
+		    int *stream_no)
+{
+    char aspect;
+    CELL curr_stream, stream_nbr, old_stream;
+    int r_nbr, c_nbr;
+    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+    int stream_node_step = 1000;
+    char this_flag_value;
+
+    G_debug(3, "continue stream");
+    
+    cseg_get(&stream, &curr_stream, r_max, c_max);
+
+    if (curr_stream <= 0) {
+	/* no confluence, just continue */
+	G_debug(3, "no confluence, just continue stream");
+	curr_stream = stream_id;
+	cseg_put(&stream, &curr_stream, r_max, c_max);
+	bseg_get(&bitflags, &this_flag_value, r_max, c_max);
+	FLAG_SET(this_flag_value, STREAMFLAG);
+	bseg_put(&bitflags, &this_flag_value, r_max, c_max);
+	return 0;
+    }
+
+    G_debug(3, "confluence");
+	    
+    /* new confluence */
+    if (stream_node[curr_stream].r != r_max ||
+	stream_node[curr_stream].c != c_max) {
+	size_t new_size;
+	
+	G_debug(3, "new confluence");
+	/* set new stream id */
+	(*stream_no)++;
+	/* add stream node */
+	if (*stream_no >= n_alloc_nodes - 1) {
+	    n_alloc_nodes += stream_node_step;
+	    stream_node =
+		(struct snode *)G_realloc(stream_node,
+					  n_alloc_nodes *
+					  sizeof(struct snode));
+	}
+	stream_node[*stream_no].r = r_max;
+	stream_node[*stream_no].c = c_max;
+	stream_node[*stream_no].id = *stream_no;
+	stream_node[*stream_no].n_trib = 0;
+	stream_node[*stream_no].n_trib_total = 0;
+	stream_node[*stream_no].n_alloc = 0;
+	stream_node[*stream_no].trib = NULL;
+	n_stream_nodes++;
+
+	/* debug */
+	if (n_stream_nodes != *stream_no)
+	    G_warning(_("BUG: stream_no %d and n_stream_nodes %d out of sync"),
+		      *stream_no, n_stream_nodes);
+
+
+	stream_node[*stream_no].n_alloc += 2;
+	new_size = stream_node[*stream_no].n_alloc * sizeof(int);
+	stream_node[*stream_no].trib =
+	    (int *)G_realloc(stream_node[*stream_no].trib, new_size);
+
+	/* add the two tributaries */
+	G_debug(3, "add tributaries");
+	stream_node[*stream_no].trib[stream_node[*stream_no].n_trib++] =
+	    curr_stream;
+	stream_node[*stream_no].trib[stream_node[*stream_no].n_trib++] =
+	    stream_id;
+
+	/* update stream IDs downstream */
+	G_debug(3, "update stream IDs downstream");
+	r_nbr = r_max;
+	c_nbr = c_max;
+	old_stream = curr_stream;
+	curr_stream = *stream_no;
+	cseg_put(&stream, &curr_stream, r_nbr, c_nbr);
+	bseg_get(&asp, &aspect, r_nbr, c_nbr);
+
+	while (aspect > 0) {
+	    r_nbr = r_nbr + asp_r[(int)aspect];
+	    c_nbr = c_nbr + asp_c[(int)aspect];
+	    cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
+	    if (stream_nbr != old_stream)
+		aspect = -1;
+	    else {
+		cseg_put(&stream, &curr_stream, r_nbr, c_nbr);
+		bseg_get(&asp, &aspect, r_nbr, c_nbr);
+	    }
+	}
+    }
+    else {
+	/* stream node already existing here */
+	G_debug(3, "existing confluence");
+	/* add new tributary to stream node */
+	if (stream_node[curr_stream].n_trib >=
+	    stream_node[curr_stream].n_alloc) {
+	    size_t new_size;
+
+	    stream_node[curr_stream].n_alloc += 2;
+	    new_size = stream_node[curr_stream].n_alloc * sizeof(int);
+	    stream_node[curr_stream].trib =
+		(int *)G_realloc(stream_node[curr_stream].trib, new_size);
+	}
+
+	stream_node[curr_stream].trib[stream_node[curr_stream].n_trib++] =
+	    stream_id;
+    }
+
+    G_debug(3, "%d tribs", stream_node[curr_stream].n_trib);
+    if (stream_node[curr_stream].n_trib == 1)
+	G_warning(_("BUG: stream node %d has only 1 tributary: %d"), curr_stream,
+		  stream_node[curr_stream].trib[0]);
+
+    return 1;
+}
+
+/*
+ * accumulate surface flow
+ */
+int do_accum(double d8cut)
+{
+    int r, c, dr, dc;
+    CELL ele_val, *ele_nbr;
+    DCELL value, *wat_nbr;
+    struct Cell_head window;
+    int mfd_cells, astar_not_set;
+    double *dist_to_nbr, *weight, sum_weight, max_weight;
+    double dx, dy;
+    int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side;
+    int is_worked;
+    char aspect;
+    double max_acc, prop;
+    int edge;
+    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
+    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
+    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
+    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
+    unsigned int workedon, killer, count;
+    char *flag_nbr, this_flag_value;
+    POINT astarpoint;
+    WAT_ALT wa;
+
+    G_message(_("Calculating flow accumulation..."));
+
+    /* distances to neighbours */
+    dist_to_nbr = (double *)G_malloc(sides * sizeof(double));
+    weight = (double *)G_malloc(sides * sizeof(double));
+    flag_nbr = (char *)G_malloc(sides * sizeof(char));
+    wat_nbr = (DCELL *)G_malloc(sides * sizeof(DCELL));
+    ele_nbr = (CELL *)G_malloc(sides * sizeof(CELL));
+
+    G_get_set_window(&window);
+
+    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	/* get r, c (r_nbr, c_nbr) for neighbours */
+	r_nbr = nextdr[ct_dir];
+	c_nbr = nextdc[ct_dir];
+	/* account for rare cases when ns_res != ew_res */
+	dy = abs(r_nbr) * window.ns_res;
+	dx = abs(c_nbr) * window.ew_res;
+	if (ct_dir < 4)
+	    dist_to_nbr[ct_dir] = dx + dy;
+	else
+	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
+    }
+
+    /* distribute and accumulate */
+    count = 0;
+    for (killer = 0; killer < n_points; killer++) {
+
+	G_percent(killer, n_points, 1);
+	
+	seg_get(&astar_pts, (char *)&astarpoint, 0, killer);
+	r = astarpoint.r;
+	c = astarpoint.c;
+
+	bseg_get(&asp, &aspect, r, c);
+
+	/* do not distribute flow along edges or out of real depressions */
+	if (aspect <= 0) {
+	    bseg_get(&bitflags, &this_flag_value, r, c);
+	    FLAG_UNSET(this_flag_value, WORKEDFLAG);
+	    bseg_put(&bitflags, &this_flag_value, r, c);
+	    continue;
+	}
+
+	if (aspect) {
+	    dr = r + asp_r[abs((int)aspect)];
+	    dc = c + asp_c[abs((int)aspect)];
+	}
+
+	r_max = dr;
+	c_max = dc;
+
+	seg_get(&watalt, (char *)&wa, r, c);
+	value = wa.wat;
+
+	/* WORKEDFLAG has been set during A* Search
+	 * reversed meaning here: 0 = done, 1 = not yet done */
+	bseg_get(&bitflags, &this_flag_value, r, c);
+	FLAG_UNSET(this_flag_value, WORKEDFLAG);
+	bseg_put(&bitflags, &this_flag_value, r, c);
+
+	/***************************************/
+	/*  get weights for flow distribution  */
+	/***************************************/
+
+	max_weight = 0;
+	sum_weight = 0;
+	np_side = -1;
+	mfd_cells = 0;
+	astar_not_set = 1;
+	ele_val = wa.ele;
+	edge = 0;
+	/* this loop is needed to get the sum of weights */
+	for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	    /* get r_nbr, c_nbr for neighbours */
+	    r_nbr = r + nextdr[ct_dir];
+	    c_nbr = c + nextdc[ct_dir];
+	    weight[ct_dir] = -1;
+	    wat_nbr[ct_dir] = 0;
+	    ele_nbr[ct_dir] = 0;
+
+	    /* check that neighbour is within region */
+	    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) {
+
+		bseg_get(&bitflags, &flag_nbr[ct_dir], r_nbr, c_nbr);
+		if ((edge = FLAG_GET(flag_nbr[ct_dir], NULLFLAG)))
+		    break;
+		seg_get(&watalt, (char *)&wa, r_nbr, c_nbr);
+		wat_nbr[ct_dir] = wa.wat;
+		ele_nbr[ct_dir] = wa.ele;
+
+		/* WORKEDFLAG has been set during A* Search
+		 * reversed meaning here: 0 = done, 1 = not yet done */
+		is_worked = FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG) == 0;
+		if (is_worked == 0) {
+		    if (ele_nbr[ct_dir] <= ele_val) {
+			if (ele_nbr[ct_dir] < ele_val) {
+			    weight[ct_dir] =
+				mfd_pow((ele_val -
+					 ele_nbr[ct_dir]) / dist_to_nbr[ct_dir]);
+			}
+			if (ele_nbr[ct_dir] == ele_val) {
+			    weight[ct_dir] =
+				mfd_pow(0.5 / dist_to_nbr[ct_dir]);
+			}
+			sum_weight += weight[ct_dir];
+			mfd_cells++;
+
+			if (weight[ct_dir] > max_weight) {
+			    max_weight = weight[ct_dir];
+			}
+
+			if (dr == r_nbr && dc == c_nbr) {
+			    astar_not_set = 0;
+			}
+		    }
+		}
+		if (dr == r_nbr && dc == c_nbr)
+		    np_side = ct_dir;
+	    }
+	    else
+		edge = 1;
+	    if (edge)
+		break;
+	}
+
+	/* do not distribute flow along edges, this