[GRASS-de] Re: [GRASS-de] Rasterfunktion zum Finden des Schwerpunktes einer Fläche?

Markus Neteler neteler at itc.it
Sa Sep 7 16:02:53 CEST 2002


On Fri, Sep 06, 2002 at 12:21:29PM +0200, Till Francke wrote:
> Hallo,
> ich suche eine Rasterfunktion, die mir von attributgleichen Flächen
> jeweils den Schwerpunkt (oder einen ähnlichen representativen Punkt,
> Medianpunkt o.ä.) liefert.

Hallo Till,

ich habe mal so ein Skript geschrieben (anbei). Es sollte
hoffentlich das tun, was du brauchst.

Benutzung:
 r.centroid ammprv 22

Die Nummer gibt die Category-number der abzufragenden Rasterflaeche
an (evtl. mit d.what.rast herausfinden).

Ergebnis z.B.
 Area of basin 22: 6208000000.00 meters^2
 Current cell resolution [meters]: EW: 500, NS: 500
 MASK = (if(double(eq(ammprv[0,0],22))))
  100%
  100%
 Calculating x_min and x_min of area...
 Calculating centroid...
 Center of gravity x_c: 1663789.04
 Center of gravity y_c: 5111224.04
 
Ciao

 Markus
-------------- nächster Teil --------------
#!/bin/sh
#
# Markus Neteler
#   neteler at itc.it
# This program is free software under the GNU GPL (>=v2).
# Calculate centroid of raster area (center of gravity)

if test "$GISBASE" = ""; then
  echo "You must be in GRASS to run this program."
  exit 1
fi

eval `g.gisenv`
: ${GISBASE?} ${GISDBASE?} ${LOCATION_NAME?} ${MAPSET?}
LOCATION=$GISDBASE/$LOCATION_NAME/$MAPSET

function usage()
{
 echo " r.centroid:"
 echo " Calculates center of gravity (centroid) of raster area"
 echo " USAGE: r.centroid raster_map area_number"
 exit 1
}

# shell check for user break (signal list: trap -l)
trap "rm -f $TMPFILE > /dev/null;\
      echo \"User break!\"; exit 1" 2 3 9 15

TMP=$$
TMPFILE=`g.tempfile pid=$TMP`
if [ $# = 0 ]
  then
     g.ask type=old element=cell unixfile=$TMPFILE
     . $TMPFILE
     MAP="${fullname}"
     echo $MAP
  elif [ $1 = "help" -o $1 = "-help" -o $1 = "-h" ] ; then
     usage
  else
     MAP=$1
fi
rm -f $TMPFILE

#error check:
if [ ! "$MAP" ]
then
  exit 1
fi

#read area number from command line:
AREANO=$2
if [ ! $AREANO ] ; then
  echo -n "Specify area for calculations: "
  read AREANO
fi

if [ $AREANO -lt 0 ] ; then
  echo "ERROR: area parameter must be a number."
  usage
  exit 1
fi

# here we go for centroid calculation:
# centroid is defined as
#               N
#  x_c = 1/A * SUM (x_i * a_i)
#              i=1 
#
#               M
#  y_c = 1/A * SUM (y_i * a_i)
#              i=1
# with 
#  N: total number of cells in x direction
#  M: total number of cells in y direction
#  x_i: distance of cell center from left boundary
#  y_i: distance of cell center from upper boundary
#  a_i: area of ith cell

# calculate area in square meters:
AREA=`r.report -qhen $MAP u=me | sed -e 's/ //' |\
      grep "^|$AREANO|." |\
      cut -d'|' -f4| awk '{printf "%.2f", $1}'`

#is area not present in map?
if [ ! $AREA ] ; then
  echo "ERROR: Selected area $AREANO not found in map $MAP."
  exit 1
fi

# determine current resolution and LOCATION units:
EWRES=`awk ' /e-w/ { print $3}' $LOCATION/WIND`
NSRES=`awk ' /n-s/ { print $3}' $LOCATION/WIND`
if [ -f $LOCATION/../PERMANENT/PROJ_UNITS ] ; then
  UNITS=`cat $LOCATION/../PERMANENT/PROJ_UNITS |\
         awk '/units:/ {print $2}'`
else
  UNITS="cellunits"
fi

echo "Area of basin $AREANO: $AREA meters^2"
echo "Current cell resolution [$UNITS]: EW: $EWRES, NS: $NSRES"

#set MASK to get only selected area:
g.rename rast=MASK,$TMP.MASK 2> /dev/null
r.mapcalc MASK="if($MAP == $AREANO)"
d.rast $MAP

echo "Calculating x_min and x_min of area..."
#calculate x_min
XMIN=`r.stats -1gnq $MAP |cut -d ' ' -f1 | awk 'BEGIN{min = 0.0}
NR == 1{min = $1}
       {if ($1 < min) {min = $1}}
END{print min}'`

#calculate y_min
YMIN=`r.stats -1gnq $MAP |cut -d ' ' -f2 | awk 'BEGIN{min = 0.0}
NR == 1{min = $1}
       {if ($1 < min) {min = $1}}
END{print min}'`

echo "Calculating centroid..."
# calculate x_c:
r.stats -1gnq $MAP |cut -d' ' -f1 | awk 'BEGIN{
    sum = 0.0 ; calc = 0.0 ; xmin2 = 0.0
    ewres = '$EWRES' ; nsres = '$NSRES'
    xmin  = '$XMIN'  ; area  = '$AREA'}
 NR == 1{xmin2 = xmin * 1.0}
        {calc = ($1 - xmin2) * ewres * nsres}
        {sum = sum + calc}
 END{printf "Center of gravity x_c: %.2f\n", sum/area + xmin2}'

# calculate y_c:
r.stats -1gnq $MAP |cut -d' ' -f2 | awk 'BEGIN{
    sum = 0.0 ; calc = 0.0 ; ymin2 = 0.0
    ewres = '$EWRES' ; nsres = '$NSRES'
    ymin  = '$YMIN'  ; area  = '$AREA'}
 NR == 1{ymin2 = ymin * 1.0 }
        {calc = ($1 - ymin2) * ewres * nsres}
        {sum = sum + calc}
 END{printf "Center of gravity y_c: %.2f\n", sum/area+ymin2}'

#restore eventual old MASK
g.remove MASK > /dev/null
g.rename rast=$TMP.MASK,MASK 2> /dev/null