#!/bin/sh

############################################################################
#
# MODULE:       r.shaded.relief
# AUTHOR(S):	CERL
#               updates: Michael Barton, 2004
#               updates: Gordon Keith, 2003
#               updates: Andreas Lange, 2001
#               updates: David Finlayson, 2001
#               updates: Markus Neteler, 2001, 1999
# PURPOSE:	Creates shaded relief map from raster elevation map (DEM)
# COPYRIGHT:	(C) 1999 - 2004 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.
#
#############################################################################
#
#   July 2007 - allow input from other mapsets (Brad Douglas)
#
#   May 2005 - fixed wrong units parameter (Markus Neteler)
#
#   September 2004 - Added z exaggeration control (Michael Barton) 
#   April 2004 - updated for GRASS 5.7 by Michael Barton 
#
#   9/2004 Adds scale factor input (as per documentation); units set scale only if specified for lat/long regions
#    Also, adds option of controlling z-exaggeration.
#
#   6/2003 fixes for Lat/Long Gordon Keith <gordon.keith@csiro.au>
#   If n is a number then the ewres and nsres are mulitplied by that scale
#    to calculate the shading.
#   If n is the letter M (either case) the number of metres is degree of
#    latitude is used as the scale.
#   If n is the letter f then the number of feet in a degree is used.
#   It scales latitude and longitude equally, so it's only approximately
#   right, but for shading its close enough. It makes the difference
#   between an unusable and usable shade.
#
#   10/2001 fix for testing for dashes in raster file name
#        by Andreas Lange <andreas.lange@rhein-main.de>
#   10/2001 added parser support - Markus Neteler
#   9/2001 fix to keep NULLs as is (was value 22 before) - Markus Neteler
#   1/2001 fix for NULL by David Finlayson <david_finlayson@yahoo.com>
#   11/99 updated $ewres to ewres() and $nsres to nsres()
#       updated number to FP in r.mapcalc statement Markus Neteler

#% Module
#%  description: Creates shaded relief map from an elevation map (DEM).
#%  keywords: raster, elevation
#% End
#% option
#%  key: map
#%  type: string
#%  gisprompt: old,cell,raster
#%  description: Input elevation map
#%  required : yes
#% end
#% option
#%  key: shadedmap
#%  type: string
#%  gisprompt: new,cell,raster
#%  description: Output shaded relief map name
#%  required : no
#% end
#% option
#%  key: altitude
#%  type: double
#%  description: Altitude of the sun in degrees above the horizon
#%  required : no
#%  options : 0-90
#%  answer: 30
#% end
#% option
#%  key: azimuth
#%  type: double
#%  description: Azimuth of the sun in degrees to the east of north
#%  required : no
#%  options : 0-360
#%  answer: 270
#% end
#% option
#%  key: zmult    
#%  type: double
#%  description: Factor for exaggerating relief
#%  required : no
#%  answer: 1
#% end
#% option
#%  key: scale
#%  type: double
#%  description: Scale factor for converting horizontal units to elevation units
#%  required : no
#%  answer: 1
#% end
#% option
#%  key: units
#%  type: string
#%  description: Set scaling factor (applies to lat./long. locations only, none: scale=1)
#%  required : no
#%  options: none,meters,feet
#%  answer: none
#% end

if  [ -z "$GISBASE" ] ; then
    echo "You must be in GRASS GIS to run this program." >&2
 exit 1
fi

# save command line
if [ "$1" != "@ARGS_PARSED@" ] ; then
    CMDLINE=`basename "$0"`
    for arg in "$@" ; do
        CMDLINE="$CMDLINE \"$arg\""
    done
    export CMDLINE
    exec g.parser "$0" "$@"
fi

# set nsres and ewres (unneeded because functions in r.mapcalc)
#nsres=`g.region -g | grep 'nsres=' | sed s/nsres=//`
#ewres=`g.region -g | grep 'ewres=' | sed s/ewres=//`

PROG=`basename "$0"`

# setting environment, so that awk works properly in all languages
unset LC_ALL
LC_NUMERIC=C
export LC_NUMERIC

alt="$GIS_OPT_ALTITUDE"
az="$GIS_OPT_AZIMUTH"
elev="$GIS_OPT_MAP"
zmult="$GIS_OPT_ZMULT"
scale="$GIS_OPT_SCALE"

eval `g.findfile element=cell file=$elev`
if [ -z "$name" ] ; then
   g.message -e  "Map <$elev> not found."
   exit 1
fi

if [ "$GIS_OPT_MAP" = "$GIS_OPT_SHADEDMAP" ]; then
	g.message -e "Input elevation map and output relief map must have different names"
	exit 1
fi

if [ -z "$GIS_OPT_SHADEDMAP" ]; then
    ELEVSHADE="${elev%%@*}.shade"
else
    ELEVSHADE="$GIS_OPT_SHADEDMAP"
fi

# test for overwrite as r.mapcalc doesn't
eval `g.findfile element=cell file="$ELEVSHADE" mapset=.`
if [ -n "$name" ] ; then
   # map already exists
   if [ -z "$GRASS_OVERWRITE" ] || [ "$GRASS_OVERWRITE" -ne 1 ] ; then
      g.message -e "option <shadedmap>: <$ELEVSHADE> exists."
      exit 1
   fi
fi

# allow - and . chars in the map name
elev="\"$elev\""
elev_out="\"$ELEVSHADE\""

#LatLong locations only:
if [ "$GIS_OPT_UNITS" = "meters" ] ; then
   #scale=111120
   scale=`echo $scale | awk '{printf("%f", $1 * 1852*60 )}'`
fi

#LatLong locations only:
if [ "$GIS_OPT_UNITS" = "feet" ] ; then
   #scale=364567.2
   scale=`echo $scale | awk '{printf("%f", $1 * 6076.12*60 )}'`
fi		

#correct azimuth to East (GRASS convention):
#  this seems to be backwards, but in fact it works so leave it.
az=`echo "$az" | awk '{print $1 - 90.0}'`

g.message "Calculating shading, please stand by."

# Note: no space allowed after \\:

r.mapcalc << EOF
$elev_out = eval( \\
 x=($zmult*$elev[-1,-1] + 2*$zmult*$elev[0,-1] + $zmult*$elev[1,-1] \\
   -$zmult*$elev[-1,1] - 2*$zmult*$elev[0,1] - $zmult*$elev[1,1])/(8.*ewres()*$scale) , \\
 y=($zmult*$elev[-1,-1] + 2*$zmult*$elev[-1,0] + $zmult*$elev[-1,1] \\
   -$zmult*$elev[1,-1] - 2*$zmult*$elev[1,0] - $zmult*$elev[1,1])/(8.*nsres()*$scale) , \\
 slope=90.-atan(sqrt(x*x + y*y)), \\
 a=round(atan(x,y)), \\
 a=if(isnull(a),1,a), \\
 aspect=if(x!=0||y!=0,if(a,a,360.)), \\
 cang = sin($alt)*sin(slope) + cos($alt)*cos(slope) * cos($az-aspect), \\
 if(cang < 0.,0.,100.*cang), \\
 if(isnull(cang), null(), 100.*cang))
EOF

if [ $? -ne 0 ] ; then 
   g.message -e "In calculation, script aborted."
   exit 1
fi

r.colors "$ELEVSHADE" color=grey

# record metadata
r.support "$ELEVSHADE" title="Shaded relief of \"$GIS_OPT_MAP\"" history=""
r.support "$ELEVSHADE" history="r.shaded.relief settings:"
r.support "$ELEVSHADE" history="  altitude=$alt  azimuth=$GIS_OPT_AZIMUTH  zmult=$zmult  scale=$GIS_OPT_SCALE"
if [ -n "$GIS_OPT_UNITS" ] ; then
   r.support map="$ELEVSHADE" history="  units=$GIS_OPT_UNITS  (adjusted scale=$scale)"
fi

if [ -n "$GIS_OPT_SHADEDMAP" ] ; then
    g.message "Shaded relief map created and named <$ELEVSHADE>."
else
    g.message "Shaded relief map created and named <$ELEVSHADE>. Consider renaming."
fi

# write cmd history:
r.support $ELEVSHADE history="${CMDLINE}"

exit 0
