[GRASS-SVN] r59072 - in grass/trunk/raster/r.li: r.li.cwed r.li.daemon r.li.dominance r.li.edgedensity r.li.mpa r.li.mps r.li.padcv r.li.padrange r.li.padsd r.li.patchdensity r.li.patchnum r.li.pielou r.li.renyi r.li.richness r.li.shannon r.li.shape r.li.simpson
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Feb 17 02:05:22 PST 2014
Author: mmetz
Date: 2014-02-17 02:05:22 -0800 (Mon, 17 Feb 2014)
New Revision: 59072
Modified:
grass/trunk/raster/r.li/r.li.cwed/cwed.c
grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html
grass/trunk/raster/r.li/r.li.daemon/daemon.c
grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html
grass/trunk/raster/r.li/r.li.dominance/dominance.c
grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html
grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c
grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html
grass/trunk/raster/r.li/r.li.mpa/mpa.c
grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html
grass/trunk/raster/r.li/r.li.mps/mps.c
grass/trunk/raster/r.li/r.li.mps/r.li.mps.html
grass/trunk/raster/r.li/r.li.padcv/padcv.c
grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html
grass/trunk/raster/r.li/r.li.padrange/padrange.c
grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html
grass/trunk/raster/r.li/r.li.padsd/padsd.c
grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html
grass/trunk/raster/r.li/r.li.patchdensity/main.c
grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html
grass/trunk/raster/r.li/r.li.patchnum/main.c
grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html
grass/trunk/raster/r.li/r.li.pielou/pielou.c
grass/trunk/raster/r.li/r.li.renyi/renyi.c
grass/trunk/raster/r.li/r.li.richness/richness.c
grass/trunk/raster/r.li/r.li.shannon/shannon.c
grass/trunk/raster/r.li/r.li.shape/main.c
grass/trunk/raster/r.li/r.li.simpson/simpson.c
Log:
r.li overhaul
Modified: grass/trunk/raster/r.li/r.li.cwed/cwed.c
===================================================================
--- grass/trunk/raster/r.li/r.li.cwed/cwed.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.cwed/cwed.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -347,16 +347,16 @@
Rast_set_c_null_value(&prevCell, 1);
Rast_set_c_null_value(&corrCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf_corr[i + ad->x];
if (masked && mask_corr[i + ad->x] == 0) {
- area--;
Rast_set_c_null_value(&corrCell, 1);
}
if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
+ area++;
+
supCell = buf_sup[i + ad->x];
+
/* calculate how many edges the cell has */
-
if (((!Rast_is_null_value(&prevCell, CELL_TYPE))) &&
(corrCell != prevCell)) {
int r = 0;
@@ -478,15 +478,15 @@
Rast_set_d_null_value(&prevCell, 1);
Rast_set_d_null_value(&corrCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf_corr[i + ad->x];
if (masked && mask_corr[i + ad->x] == 0) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
+ area++;
supCell = buf_sup[i + ad->x];
- /* calculate how many edge the cell has */
+
+ /* calculate how many edges the cell has */
if (((!Rast_is_null_value(&prevCell, DCELL_TYPE))) &&
(corrCell != prevCell)) {
int r = 0;
@@ -609,15 +609,16 @@
Rast_set_f_null_value(&prevCell, 1);
Rast_set_f_null_value(&corrCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf_corr[i + ad->x];
if (masked && mask_corr[i + ad->x] == 0) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
+ area++;
+
supCell = buf_sup[i + ad->x];
+ /* calculate how many edges the cell has */
if (((!Rast_is_null_value(&prevCell, FCELL_TYPE))) &&
(corrCell != prevCell)) {
int r = 0;
Modified: grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html
===================================================================
--- grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -28,7 +28,7 @@
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
<!-- TODO: verify next: -->
-If the input raster map contains only NULL values it is considered to
+If the sample area contains only NULL values it is considered to
have 0 patch and CWED=0. If Area is 0 <em>r.li.cwed</em> returns -1.
This is only possible if the map is masked.<br>
If you want to change these -1 values to NULL, run subsequently on the resulting map:
@@ -67,7 +67,8 @@
<h2>AUTHORS</h2>
Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
<p>
<i>Last changed: $Date$</i></p>
Modified: grass/trunk/raster/r.li/r.li.daemon/daemon.c
===================================================================
--- grass/trunk/raster/r.li/r.li.daemon/daemon.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.daemon/daemon.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -565,7 +565,7 @@
char s[100];
int len;
- sprintf(s, "RESULT %i|%f\n", m.f.f_d.aid, m.f.f_d.res);
+ sprintf(s, "RESULT %i|%.15g\n", m.f.f_d.aid, m.f.f_d.res);
len = strlen(s);
if (write(out, s, len) == len)
Modified: grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html
===================================================================
--- grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -87,7 +87,8 @@
Claudio Porta and Lucio Davide Spano, students of Computer Science
University of Pisa (Italy).<br>
Commission from Faunalia Pontedera (PI)<br>
-Rewritten from "r.le.setup" by William L. Baker
+Rewritten from "r.le.setup" by William L. Baker<br>
+Rewritten to produce correct results by Markus Metz<br>
This program is free software under the GPL (>=v2)
Read the COPYING file that comes with GRASS for details.
Modified: grass/trunk/raster/r.li/r.li.dominance/dominance.c
===================================================================
--- grass/trunk/raster/r.li/r.li.dominance/dominance.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.dominance/dominance.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,19 @@
-/*
- * \brief calculates dominance's diversity index
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.dominance
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Rewrite: Markus Metz
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
+ * PURPOSE: calculates dominance diversity index
+ * COPYRIGHT: (C) 2007-2014 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/raster.h>
@@ -17,10 +23,9 @@
#include <fcntl.h>
#include <math.h>
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
#include "../r.li.daemon/avlDefs.h"
#include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
/* template is shannon */
@@ -101,42 +106,31 @@
{
CELL *buf;
CELL corrCell;
+ CELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- generic_cell cc;
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = CELL_TYPE;
+ uc.t = CELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
- mask_buf = G_malloc(Rast_window_cols() * sizeof(int));
+ mask_buf = G_malloc(ad->cl * sizeof(int));
if (mask_buf == NULL) {
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
@@ -144,10 +138,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -155,31 +146,42 @@
}
}
+ buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+ Rast_set_c_null_value(&precCell, 1);
+
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.c = corrCell;
- albero = avl_make(cc, 1);
-
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.c = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -197,56 +199,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
- }
- } /* end for */
- } /* end for */
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
/*last closing */
- if (a != 0 && albero != NULL) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+ m++;
+ }
+ else {
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
+ }
- array = G_malloc(m * sizeof(AVL_tableRow *));
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
+ array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
G_free(array);
- if (m != 0)
- indice = log((double)m) + somma;
- else
- indice = 0;
+ *result = log(m) + shannon;
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
@@ -256,37 +293,26 @@
{
DCELL *buf;
DCELL corrCell;
+ DCELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- generic_cell cc;
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = DCELL_TYPE;
+ uc.t = DCELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -299,10 +325,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -310,30 +333,42 @@
}
}
- for (i = 0; i < ad->cl; i++) { /* for each dcell in the row */
- area++;
+ buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_d_null_value(&precCell, 1);
+
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.dc = corrCell;
- albero = avl_make(cc, 1);
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.dc = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -351,56 +386,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
+
+ /*last closing */
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
}
- } /*close for */
- } /*close for */
+ m++;
+ }
+ else {
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
+ }
- /*last closing */
- if (a != 0 && albero != NULL) {
- array = G_malloc(m * sizeof(AVL_tableRow *));
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
+ array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning
- ("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
G_free(array);
- if (m != 0)
- indice = log((double)m) + somma;
- else
- indice = 0;
+ *result = log(m) + shannon;
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
@@ -410,37 +480,26 @@
{
FCELL *buf;
FCELL corrCell;
+ FCELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- generic_cell cc;
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = FCELL_TYPE;
+ uc.t = FCELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -453,10 +512,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -464,29 +520,42 @@
}
}
- for (i = 0; i < ad->cl; i++) { /* for each fcell in the row */
- area++;
+ buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_f_null_value(&precCell, 1);
+
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.fc = corrCell;
- albero = avl_make(cc, 1);
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.fc = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -504,55 +573,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
+
+ /*last closing */
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
}
+ m++;
}
+ else {
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
}
- /*last closing */
- if (a != 0 && albero != NULL) {
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
G_free(array);
- if (m != 0)
- indice = log((double)m) + somma;
- else
- indice = 0;
+ *result = log(m) + shannon;
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html
===================================================================
--- grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -18,13 +18,8 @@
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
<!-- TODO: verify next: -->
-If the input raster map contains only NULL values then <em>r.li.dominance</em>
-returns -1.<br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+If the input raster map contains only NULL values then
+<em>r.li.dominance</em> returns NULL.<br>
<h2>EXAMPLES</h2>
To calculate the dominance diversity index on map <em>my_map</em>, using
@@ -53,7 +48,8 @@
<h2>AUTHORS</h2>
Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
<p>
<i>Last changed: $Date$</i></p>
Modified: grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c
===================================================================
--- grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -116,7 +116,6 @@
int calculate(int fd, struct area_entry *ad, char **valore, double *result)
{
- double indice = 0;
double e = 0;
double somma = 0;
double area = 0;
@@ -204,9 +203,8 @@
buf_inf = buf_null;
}
- /*read mask if needed */
+ /* read mask if needed */
if (masked) {
-
mask_tmp = mask_sup;
mask_sup = mask_corr;
mask_corr = mask_inf;
@@ -230,16 +228,15 @@
Rast_set_c_null_value(&prevCell, 1);
Rast_set_c_null_value(&corrCell, 1);
- for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
+ for (i = 0; i < ad->cl; i++) {
corrCell = buf_corr[i + ad->x];
if (masked && mask_corr[i + ad->x] == 0) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
+ area++;
if ((i + 1) == ad->cl) /*last cell of the row */
Rast_set_c_null_value(&nextCell, 1);
else if (masked && mask_corr[i + 1 + ad->x] == 0)
@@ -258,7 +255,6 @@
infCell = buf_inf[i + ad->x];
/* calculate how many edges the cell has */
-
if ((Rast_is_null_value(&prevCell, CELL_TYPE)) ||
(corrCell != prevCell)) {
bordoCorr++;
@@ -274,13 +270,12 @@
bordoCorr++;
}
-
if ((Rast_is_null_value(&nextCell, CELL_TYPE)) ||
(corrCell != nextCell)) {
bordoCorr++;
}
- /*store the result in the tree */
+ /* store the result in the tree */
if (albero == NULL) {
c1.val.c = corrCell;
albero = avl_make(c1, bordoCorr);
@@ -316,18 +311,14 @@
}
}
}
-
bordoCorr = 0;
}
-
prevCell = corrCell;
}
}
/* calculate index */
- if (area == 0)
- indice = -1;
- else {
+ if (area > 0) {
if (valore != NULL) { /* only 1 class */
char *sval;
int val;
@@ -340,10 +331,8 @@
c1.val.c = cella;
e = (double)howManyCell(albero, c1);
somma = e;
-
}
else { /* all classes */
-
array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
@@ -361,10 +350,11 @@
G_free(array);
}
- indice = somma * 10000 / area;
+ *result = somma * 10000 / area;
}
+ else
+ Rast_set_d_null_value(result);
- *result = indice;
if (masked) {
close(mask_fd);
G_free(mask_inf);
@@ -380,7 +370,6 @@
int calculateD(int fd, struct area_entry *ad, char **valore, double *result)
{
- double indice = 0;
double e = 0;
double somma = 0;
double area = 0;
@@ -472,7 +461,7 @@
buf_inf = buf_null;
}
- /*read mask if needed */
+ /* read mask if needed */
if (masked) {
mask_tmp = mask_sup;
@@ -499,17 +488,14 @@
Rast_set_d_null_value(&corrCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
-
- area++;
corrCell = buf_corr[i + ad->x];
if (masked && mask_corr[i + ad->x] == 0) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
-
+ area++;
if ((i + 1) == ad->cl) /*last cell of the row */
Rast_set_d_null_value(&nextCell, 1);
else if (masked && mask_corr[i + 1 + ad->x] == 0)
@@ -549,7 +535,7 @@
bordoCorr++;
}
- /*store the result in the tree */
+ /* store the result in the tree */
if (albero == NULL) {
c1.val.dc = corrCell;
albero = avl_make(c1, bordoCorr);
@@ -585,19 +571,14 @@
}
}
}
-
bordoCorr = 0;
-
}
-
prevCell = corrCell;
}
}
/* calculate index */
- if (area == 0)
- indice = -1;
- else {
+ if (area > 0) {
if (valore != NULL) { /* only 1 class */
char *sval;
double val;
@@ -628,10 +609,11 @@
}
G_free(array);
}
- indice = somma * 10000 / area;
+ *result = somma * 10000 / area;
}
+ else
+ Rast_set_d_null_value(result);
- *result = indice;
if (masked) {
close(mask_fd);
G_free(mask_inf);
@@ -647,7 +629,6 @@
int calculateF(int fd, struct area_entry *ad, char **valore, double *result)
{
- double indice = 0;
double e = 0;
double somma = 0;
double area = 0;
@@ -731,16 +712,14 @@
buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
if ((j + 1) < ad->rl) { /* not last row */
-
buf_inf = RLI_get_fcell_raster_row(fd, 1 + j + ad->y, ad);
}
else {
buf_inf = buf_null;
}
- /*read mask if needed */
+ /* read mask if needed */
if (masked) {
-
mask_tmp = mask_sup;
mask_sup = mask_corr;
mask_corr = mask_inf;
@@ -765,16 +744,14 @@
Rast_set_f_null_value(&corrCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf_corr[i + ad->x];
if (masked && mask_corr[i + ad->x] == 0) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
-
+ area++;
if ((i + 1) == ad->cl) /*last cell of the row */
Rast_set_f_null_value(&nextCell, 1);
else if (masked && mask_corr[i + 1 + ad->x] == 0)
@@ -792,8 +769,7 @@
else
infCell = buf_inf[i + ad->x];
- /* calculate how many edge the cell has */
-
+ /* calculate how many edges the cell has */
if ((Rast_is_null_value(&prevCell, FCELL_TYPE)) ||
(corrCell != prevCell)) {
bordoCorr++;
@@ -814,9 +790,9 @@
bordoCorr++;
}
- /*store the result in the tree */
+ /* store the result in the tree */
if (albero == NULL) {
- c1.val.c = corrCell;
+ c1.val.fc = corrCell;
albero = avl_make(c1, bordoCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
@@ -825,7 +801,7 @@
m++;
}
else {
- c1.val.c = corrCell;
+ c1.val.fc = corrCell;
ris = avl_add(&albero, c1, bordoCorr);
switch (ris) {
@@ -850,19 +826,14 @@
}
}
}
-
bordoCorr = 0;
-
}
-
prevCell = corrCell;
}
}
/* calculate index */
- if (area == 0)
- indice = -1;
- else {
+ if (area > 0) {
if (valore != NULL) { /* only 1 class */
char *sval;
float val;
@@ -894,10 +865,11 @@
}
G_free(array);
}
- indice = somma * 10000 / area;
+ *result = somma * 10000 / area;
}
+ else
+ Rast_set_d_null_value(result);
- *result = indice;
if (masked) {
close(mask_fd);
G_free(mask_inf);
Modified: grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html
===================================================================
--- grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -3,10 +3,11 @@
<em>r.li.edgedensity </em>calculates:<br>
<br>
<ul>
- <li> the density of all the edge of patch i
+ <li> the density of all edges of patch type <em>k</em>
<img alt="rliEdgeDensity formula1" src="rliEdgeDensity_formula1.png">
, or
- <li> the density of all the edge in the sampling area if i isn't specified,
+ <li> the density of all edges in the sampling area if <em>k</em> is
+ not specified,
<img alt="rliEdgeDensity formula2" src="rliEdgeDensity_formula2.png">
</ul>
<p>with:
@@ -14,7 +15,8 @@
<li><b>k</b>: patch type</li>
<li><b>m</b>: number of patch types</li>
<li><b>n</b>: number of edge segments of patch type k</li>
-<li><b>e<small><small>ik </small></small></b>:total length of edge in landscape involving patch type k</li>
+<li><b>e<small><small>ik </small></small></b>:total edge length in
+the landscape involving patch type k</li>
<li> <b>Area</b>: total landscape area</li>
</ul>
@@ -70,7 +72,8 @@
<h2>AUTHORS</h2>
Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.mpa/mpa.c
===================================================================
--- grass/trunk/raster/r.li/r.li.mpa/mpa.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mpa/mpa.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -106,7 +106,6 @@
int masked = FALSE;
double area = 0;
- double indice = 0;
double somma = 0;
/* open mask if needed */
@@ -123,44 +122,41 @@
masked = TRUE;
}
+ for (j = 0; j < ad->rl; j++) {
+ buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
- for (j = 0; j < ad->rl; j++) { /*for each raster row */
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad); /*read raster row */
-
- if (masked) { /*read mask row if needed */
-
+ if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
return RLI_ERRORE;
}
}
- for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
- area++;
+ for (i = 0; i < ad->cl; i++) {
if (masked && mask_buf[i + ad->x] == 0) {
Rast_set_c_null_value(&buf[i + ad->x], 1);
- area--;
}
- if (!(Rast_is_null_value(&buf[i + ad->x], CELL_TYPE))) { /*if it's a cell to consider */
+ if (!(Rast_is_c_null_value(&buf[i + ad->x]))) {
+ area++;
somma = somma + buf[i + ad->x];
}
}
}
-
- if (area == 0)
- indice = (double)-1;
+ if (area > 0)
+ *result = somma / area;
else
- indice = somma / area;
+ Rast_set_d_null_value(result);
- *result = indice;
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
+
return RLI_OK;
}
+
int calculateD(int fd, struct area_entry *ad, double *result)
{
DCELL *buf;
@@ -170,7 +166,6 @@
int masked = FALSE;
double area = 0;
- double indice = 0;
double somma = 0;
/* open mask if needed */
@@ -187,39 +182,37 @@
masked = TRUE;
}
- for (j = 0; j < ad->rl; j++) { /*for each raster row */
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad); /*read raster row */
+ for (j = 0; j < ad->rl; j++) {
+ buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
- if (masked) { /*read mask row if needed */
-
+ if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
return RLI_ERRORE;
}
}
- for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
- area++;
- if ((masked) && (mask_buf[i + ad->x] == 0)) {
- area--;
+ for (i = 0; i < ad->cl; i++) {
+ if (masked && mask_buf[i + ad->x] == 0) {
Rast_set_d_null_value(&buf[i + ad->x], 1);
}
- if (!(Rast_is_null_value(&buf[i + ad->x], DCELL_TYPE))) {
+ if (!(Rast_is_d_null_value(&buf[i + ad->x]))) {
+ area++;
somma = somma + buf[i + ad->x];
}
}
}
- if (area == 0)
- indice = (double)-1;
+ if (area > 0)
+ *result = somma / area;
else
- indice = somma / area;
+ Rast_set_d_null_value(result);
- *result = indice;
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
+
return RLI_OK;
}
@@ -232,7 +225,6 @@
int masked = FALSE;
double area = 0;
- double indice = 0;
double somma = 0;
/* open mask if needed */
@@ -249,39 +241,36 @@
masked = TRUE;
}
- for (j = 0; j < ad->rl; j++) { /*for each raster row */
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad); /*read raster row */
+ for (j = 0; j < ad->rl; j++) {
+ buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
- if (masked) { /*read mask row if needed */
-
+ if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
return RLI_ERRORE;
}
}
- for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
- area++;
-
- if ((masked) && (mask_buf[i + ad->x] == 0)) {
- area--;
+ for (i = 0; i < ad->cl; i++) {
+ if (masked && mask_buf[i + ad->x] == 0) {
Rast_set_f_null_value(&buf[i + ad->x], 1);
}
- if (!(Rast_is_null_value(&buf[i + ad->x], FCELL_TYPE))) {
+ if (!(Rast_is_f_null_value(&buf[i + ad->x]))) {
+ area++;
somma = somma + buf[i + ad->x];
}
}
}
- if (area == 0)
- indice = (double)-1;
+ if (area > 0)
+ *result = somma / area;
else
- indice = somma / area;
+ Rast_set_d_null_value(result);
- *result = indice;
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
+
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html
===================================================================
--- grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -56,7 +56,8 @@
<h2>AUTHORS</h2>
Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.mps/mps.c
===================================================================
--- grass/trunk/raster/r.li/r.li.mps/mps.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mps/mps.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,20 @@
-/*
- * \brief calculates mean patch size index
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.patchnum
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Rewrite: Markus Metz
+ * Patch identification: Michael Shapiro - CERL
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
+ * PURPOSE: calculates mean patch size index
+ * COPYRIGHT: (C) 2007-2014 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 <fcntl.h>
@@ -17,16 +24,21 @@
#include <grass/raster.h>
#include <grass/glocale.h>
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
#include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
+/* template is patchnum */
-int calculate(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
-int calculateD(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
-int calculateF(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
+/* cell count and type of each patch */
+struct pst {
+ long count;
+ generic_cell type;
+};
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
int main(int argc, char *argv[])
{
struct Option *raster, *conf, *output;
@@ -62,24 +74,21 @@
{
int ris = 0;
double indice = 0;
- struct Cell_head hd;
- Rast_get_cellhd(ad->raster, "", &hd);
-
switch (ad->data_type) {
case CELL_TYPE:
{
- ris = calculate(fd, ad, hd, &indice);
+ ris = calculate(fd, ad, &indice);
break;
}
case DCELL_TYPE:
{
- ris = calculateD(fd, ad, hd, &indice);
+ ris = calculateD(fd, ad, &indice);
break;
}
case FCELL_TYPE:
{
- ris = calculateF(fd, ad, hd, &indice);
+ ris = calculateF(fd, ad, &indice);
break;
}
default:
@@ -98,39 +107,38 @@
}
-int calculate(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
+int calculate(int fd, struct area_entry *ad, double *result)
{
CELL *buf, *buf_sup, *buf_null;
+ CELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- CELL corrCell;
- CELL precCell;
- CELL supCell;
+ Rast_get_cellhd(ad->raster, "", &hd);
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
+ buf_null = Rast_allocate_c_buf();
+ Rast_set_c_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long uno = 1;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
- double indice = 0;
- double area = 0; /*if all cells are null area=0 */
- double areaCorrect = 0;
- double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
- avlID_tree albero = NULL;
- avlID_table *array;
-
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -139,289 +147,156 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- buf_null = Rast_allocate_c_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
-
- /*the first time buf_sup is all null */
- Rast_set_c_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
- }
-
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_c_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
- corrCell = buf[i + ad->x];
-
- if ((masked) && (mask_buf[i + ad->x] == 0)) {
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
}
- /*valid cell */
- if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
- area++;
+ if (Rast_is_c_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&supCell, 1);
+ }
- supCell = buf_sup[i + ad->x];
+ if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- if (corrCell != precCell) {
- if (corrCell != supCell) {
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else { /*not first patch */
- /* put in the tree previous values */
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+ if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
- }
- else { /* tree not null */
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
-
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
}
- else { /*current cell and upper cell are equal */
- if ((corrCell == precCell) &&
- (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
- long r = 0;
- long del = mask_patch_sup[i];
-
- r = avlID_sub(&albero, del);
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (i < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
- else {
- r = ad->cl + 1;
- }
- }
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
-
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
- else { /* tree not null */
-
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
-
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- }
- else { /*current cell and previous cell are equal */
-
- if ((corrCell == supCell) &&
- (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
- int l;
-
- mask_patch_corr[i] = mask_patch_sup[i];
- l = i - 1;
- while (l >= 0) {
- if (mask_patch_corr[l] == idCorr) {
- mask_patch_corr[l] = mask_patch_sup[i];
- l--;
- }
- else {
- l = (-1);
- }
- }
- lastId--;
- idCorr = mask_patch_sup[i];
- }
else {
- mask_patch_corr[i] = idCorr;
+ pst[new_pid].count++;
}
}
+ connected = 1;
}
- else { /*cell not to consider or cell is null */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (area != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
-
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
-
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0)
- doppi++;
- }
- npatch = npatch - doppi;
-
- /*calculate distance */
+ /* calculate distance */
G_begin_distance_calculations();
/* EW Dist at North edge */
EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
@@ -432,60 +307,61 @@
/* NS Dist at West edge */
NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
- (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
- indice = areaCorrect / npatch;
- G_free(array);
+ area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
+
+ *result = (area_units / (npatch * 10000);
}
- else
- indice = (double)(0);
+ else {
+ *result = 0;
+ }
- *result = indice;
-
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
-
- G_free(mask_patch_corr);
- G_free(mask_patch_sup);
G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- avlID_destroy(albero);
-
return RLI_OK;
}
-int calculateD(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
+int calculateD(int fd, struct area_entry *ad, double *result)
{
DCELL *buf, *buf_sup, *buf_null;
- DCELL corrCell;
- DCELL precCell;
- DCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long uno = 1;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double area = 0; /*if all cells are null area=0 */
- double areaCorrect = 0;
- double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ DCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- avlID_tree albero = NULL;
- avlID_table *array;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_d_buf();
+ Rast_set_d_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -494,289 +370,156 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- buf_null = Rast_allocate_d_buf();
-
- /*the first time buf_sup is all null */
- Rast_set_d_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
- }
-
- /*read each row and put in an avlId tree cell value with the number of cells which have that value */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_d_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
- corrCell = buf[i + ad->x];
-
- if ((masked) && (mask_buf[i + ad->x] == 0)) {
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
}
- if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
- area++;
+ if (Rast_is_d_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&supCell, 1);
+ }
- supCell = buf_sup[i + ad->x];
+ if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- if (corrCell != precCell) {
- if (corrCell != supCell) {
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else { /*not first patch */
- /* put in the tree previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+ if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
- }
- else { /* tree not null */
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
-
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
}
- else { /*current cell and upper cell are equal */
- if ((corrCell == precCell) &&
- (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
- long r = 0;
- long del = mask_patch_sup[i];
-
- /*Remove one patch because it makes part of a patch already found */
- r = avlID_sub(&albero, del);
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
-
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (i < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
- else {
- r = ad->cl + 1;
- }
- }
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
-
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
- else { /*tree not null */
-
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
-
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
- else { /*current cell and previous cell are equals */
+ connected = 1;
+ }
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
- if ((corrCell == supCell) &&
- (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
- int l;
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
- mask_patch_corr[i] = mask_patch_sup[i];
- l = i - 1;
- while (l >= 0) {
- if (mask_patch_corr[l] == idCorr) {
- mask_patch_corr[l] = mask_patch_sup[i];
- l--;
- }
- else {
- l = (-1);
- }
- }
- lastId--;
- idCorr = mask_patch_sup[i];
- }
- else {
- mask_patch_corr[i] = idCorr;
- }
-
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
- }
- else { /*cell null or not to consider */
- mask_patch_corr[i] = 0;
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
- if (area != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
-
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
-
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
-
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0)
- doppi++;
-
- }
- npatch = npatch - doppi;
-
- /*calculate distance */
+ /* calculate distance */
G_begin_distance_calculations();
/* EW Dist at North edge */
EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
@@ -787,65 +530,61 @@
/* NS Dist at West edge */
NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
- (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
- indice = areaCorrect / npatch;
- G_free(array);
+ area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
+
+ *result = (area_units / npatch) * 10000;
}
- else
- indice = (double)(0);
+ else {
+ *result = 0;
+ }
-
- *result = indice;
-
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
-
- G_free(mask_patch_corr);
- G_free(mask_patch_sup);
G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- avlID_destroy(albero);
-
return RLI_OK;
}
-int calculateF(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
+int calculateF(int fd, struct area_entry *ad, double *result)
{
FCELL *buf, *buf_sup, *buf_null;
+ FCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- FCELL corrCell;
- FCELL precCell;
- FCELL supCell;
+ Rast_get_cellhd(ad->raster, "", &hd);
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
+ buf_null = Rast_allocate_f_buf();
+ Rast_set_f_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long uno = 1;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
- double indice = 0;
- double area = 0; /*if all cells are null area=0 */
- double areaCorrect = 0;
- double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
- avlID_tree albero = NULL;
- avlID_table *array;
-
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -854,284 +593,156 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- buf_null = Rast_allocate_f_buf();
-
- /*the first time buf_sup is all null */
- Rast_set_f_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
- }
-
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_f_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
- corrCell = buf[i + ad->x];
- if (((masked) && (mask_buf[i + ad->x] == 0))) {
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
}
- if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
- area++;
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_f_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- if (corrCell != supCell) {
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else { /*not first patch */
- /* put in the tree previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+ if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- }
- else { /*tree not empty */
+ if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
}
- else { /*current cell and upper cell are equal */
- if ((corrCell == precCell) &&
- (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
- long r = 0;
- long del = mask_patch_sup[i];
-
- r = avlID_sub(&albero, del);
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (i < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
- else {
- r = ad->cl + 1;
- }
- }
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
-
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
- else { /*the tree (albero) isn't null */
-
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
-
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
- else { /*current cell and previous cell are equal */
+ connected = 1;
+ }
- if ((corrCell == supCell) &&
- (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
- int l;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
- mask_patch_corr[i] = mask_patch_sup[i];
- l = i - 1;
- while (l >= 0) {
- if (mask_patch_corr[l] == idCorr) {
- mask_patch_corr[l] = mask_patch_sup[i];
- l--;
- }
- else {
- l = (-1);
- }
- }
- lastId--;
- idCorr = mask_patch_sup[i];
- }
- else {
- mask_patch_corr[i] = idCorr;
- }
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
- }
- else { /*null cell or cell not to consider */
- mask_patch_corr[i] = 0;
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (area != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, uno);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, uno);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
-
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
-
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0)
- doppi++;
-
- }
- npatch = npatch - doppi;
-
- /*calculate distance */
+ /* calculate distance */
G_begin_distance_calculations();
/* EW Dist at North edge */
EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
@@ -1142,26 +753,24 @@
/* NS Dist at West edge */
NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
- (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
- indice = areaCorrect / npatch;
- G_free(array);
+ area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
+
+ *result = (area_units / npatch) * 10000;
}
- else
- indice = (double)(0);
+ else {
+ *result = 0;
+ }
- *result = indice;
-
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
-
- G_free(mask_patch_corr);
- G_free(mask_patch_sup);
G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- avlID_destroy(albero);
-
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.mps/r.li.mps.html
===================================================================
--- grass/trunk/raster/r.li/r.li.mps/r.li.mps.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mps/r.li.mps.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,7 +1,7 @@
<h2>DESCRIPTION</h2>
-<em>r.li.mps</em> (mean patch size) calculates the mean size of the patches
-in the sampling area as:<br>
+<em>r.li.mps</em> (mean patch size) calculates the mean size of the
+patches in the sampling area as:<br>
<img src="rlimps_formula.png" alt="rliMps formula"><br>
with:
@@ -10,6 +10,12 @@
<li><b>Npatch</b>: number of patches</li>
</ul>
+The unit of the mean size is hectare.
+
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells
+are ignored when tracing a patch.
+
<h2>NOTES</h2>
Do not use absolute path names for the <b>output</b> map/file.
@@ -17,14 +23,8 @@
output will be a raster map, otherwise an ASCII file will be generated in
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
-<!-- TODO: verify next: -->
-If the input raster contains NULL value cells, <em>r.li.mps</em>
-returns 0 for these cells. <br>
-If you want to change these 0 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=0 input=my_map
-</pre></div>
-after index calculation.
+If the sample area contains only NULL value cells, <em>r.li.mps</em>
+returns 0 (zero). <br>
<h2>EXAMPLES</h2>
To calculate mean path size index on map <em>my_map</em>, using
@@ -52,8 +52,8 @@
Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
<h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.padcv/padcv.c
===================================================================
--- grass/trunk/raster/r.li/r.li.padcv/padcv.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padcv/padcv.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,21 @@
-/*
- * \brief calculates coefficient of variation of patch area
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.padcv
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Fixes: Markus Neteler <neteler itc.it>
+ * Rewrite: Markus Metz
+ * Patch identification: Michael Shapiro - CERL
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
+ * PURPOSE: calculates coefficient of variation of patch areas
+ * COPYRIGHT: (C) 2007-2014 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 <fcntl.h>
@@ -17,12 +25,17 @@
#include <grass/raster.h>
#include <grass/glocale.h>
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
-#include "../r.li.daemon/GenericCell.h"
#include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+ long count;
+ generic_cell type;
+};
+
int calculate(int fd, struct area_entry *ad, double *result);
int calculateD(int fd, struct area_entry *ad, double *result);
int calculateF(int fd, struct area_entry *ad, double *result);
@@ -94,41 +107,39 @@
return RLI_OK;
}
+
int calculate(int fd, struct area_entry *ad, double *result)
{
CELL *buf, *buf_sup, *buf_null;
- CELL corrCell;
- CELL precCell;
- CELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long np = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double somma = 0;
- double area = 0;
- double mn = 0;
- double sd = 0;
- double cv = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ CELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = CELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_c_buf();
+ Rast_set_c_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -137,366 +148,241 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_c_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_c_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_c_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) {
- /* for each cell in the row */
- area++;
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_c_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first found patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
- }
- else {
- /* current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
- }
- }
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
+ if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
-
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else {
- mask_patch_corr[i] = idCorr;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
+ else {
+ pst[new_pid].count++;
}
-
- totCorr++;
}
+ connected = 1;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double pcv;
+ double diff;
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0) {
- doppi++;
- }
- }
- np = npatch;
- npatch = npatch - doppi;
- mn = areaPatch / npatch;
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- /* calculate summary */
- for (i = 0; i < np; i++) {
- long areaPi = 0;
- double diff;
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
- if (array[i]->tot != 0) {
- ris = ris + array[i]->tot;
- areaPi = (double)array[i]->tot;
- diff = areaPi - mn;
- somma = somma + (diff * diff);
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
- sd = sqrt(somma / npatch);
- cv = sd * 100 / mn;
- indice = cv;
- G_free(array);
+ psd = sqrt(psd / npatch);
+ pcv = psd * 100 / mps;
+ *result = pcv;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
+
int calculateD(int fd, struct area_entry *ad, double *result)
{
- DCELL *buf , *buf_sup, *buf_null;
- DCELL corrCell;
- DCELL precCell;
- DCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long np = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double somma = 0;
- double area = 0;
- double mn = 0;
- double sd = 0;
- double cv = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ DCELL *buf, *buf_sup, *buf_null;
+ DCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = DCELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_d_buf();
+ Rast_set_d_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -505,367 +391,241 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_d_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_d_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_d_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) {
- /* for each dcell in the row */
- area++;
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_d_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
+ if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
+ if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
}
- else {
- /*current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
- }
- }
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
-
-
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
-
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
-
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else {
- mask_patch_corr[i] = idCorr;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
+ else {
+ pst[new_pid].count++;
}
-
- totCorr++;
}
+ connected = 1;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double pcv;
+ double diff;
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0) {
- doppi++;
- }
- }
- np = npatch;
- npatch = npatch - doppi;
- mn = areaPatch / npatch;
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- /* calculate summary */
- for (i = 0; i < np; i++) {
- long areaPi = 0;
- double diff;
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
- if (array[i]->tot != 0) {
- ris = ris + array[i]->tot;
- areaPi = (double)array[i]->tot;
- diff = areaPi - mn;
- somma = somma + (diff * diff);
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
- sd = sqrt(somma / npatch);
- cv = sd * 100 / mn;
- indice = cv;
- G_free(array);
+ psd = sqrt(psd / npatch);
+ pcv = psd * 100 / mps;
+ *result = pcv;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
+
int calculateF(int fd, struct area_entry *ad, double *result)
{
FCELL *buf, *buf_sup, *buf_null;
- FCELL corrCell;
- FCELL precCell;
- FCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- long npatch = 0;
- long np = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double somma = 0;
- double area = 0;
- double mn = 0;
- double sd = 0;
- double cv = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ FCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = FCELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_f_buf();
+ Rast_set_f_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -874,331 +634,204 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_f_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_f_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_f_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) {
- /* for each fcell in the row */
- area++;
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
- if (i > 0)
- precCell = buf[i - 1 + ad->x];
- if (j == 0)
- Rast_set_f_null_value(&supCell, 1);
- else
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_f_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
- }
- else {
- /*current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
- }
- }
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
+ if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else {
- mask_patch_corr[i] = idCorr;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
+ else {
+ pst[new_pid].count++;
}
-
- totCorr++;
}
+ connected = 1;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double pcv;
+ double diff;
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0) {
- doppi++;
- }
- }
- np = npatch;
- npatch = npatch - doppi;
- mn = areaPatch / npatch;
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- /* calculate summary */
- for (i = 0; i < np; i++) {
- long areaPi = 0;
- double diff;
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
- if (array[i]->tot != 0) {
- ris = ris + array[i]->tot;
- areaPi = (double)array[i]->tot;
- diff = areaPi - mn;
- somma = somma + (diff * diff);
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
- sd = sqrt(somma / npatch);
- cv = sd * 100 / mn;
- indice = cv;
- G_free(array);
+ psd = sqrt(psd / npatch);
+ pcv = psd * 100 / mps;
+ *result = pcv;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html
===================================================================
--- grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,7 +1,7 @@
<h2>DESCRIPTION</h2>
-<em>r.li.padcv</em> (patch area distribution coefficient of variation) calculates
-as:<br>
+<em>r.li.padcv</em> calculates the coefficient of variation of patch
+area sizes in hectares as:<br>
<img src="rlipadcv_formula1.png" alt="rlipadcv formula"> <br>
with:<br>
<ul>
@@ -9,7 +9,7 @@
<img src="rlipadcv_formula2.png"> </li>
<li><b>MPS</b>: mean patch area size </li>
<li><b>a<small><small>i</small></small></b>: area of patch i</li>
- <li><b>N<small>patch</small></b>: number of patch</li>
+ <li><b>N<small>patch</small></b>: number of patches</li>
</ul>
<h2>NOTES</h2>
@@ -19,13 +19,7 @@
output will be a raster map, otherwise an ASCII file will be generated in
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
-If input raster is not full of null values <em>r.li.padcv</em> returns a value >=0 that is PADcv. <br>
-If the input raster map contains only NULL values then <em>r.li.padcv</em> returns -1. <br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+The result is NULL if the sample area contains only NULL values.
<h2>EXAMPLES</h2>
To calculate patch area distribution coefficient of variation index on map <em>my_map</em>, using
@@ -53,8 +47,8 @@
Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
<h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.padrange/padrange.c
===================================================================
--- grass/trunk/raster/r.li/r.li.padrange/padrange.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padrange/padrange.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,28 +1,41 @@
-/*
- * \brief calculates range of patch area size
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.padrange
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Fixes: Markus Neteler <neteler itc.it>
+ * Rewrite: Markus Metz
+ * Patch identification: Michael Shapiro - CERL
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
+ * PURPOSE: calculates calculates standard deviation of patch areas
+ * COPYRIGHT: (C) 2007-2014 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/raster.h>
-#include <grass/glocale.h>
-
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
-#include "../r.li.daemon/GenericCell.h"
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
#include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+ long count;
+ generic_cell type;
+};
+
int calculate(int fd, struct area_entry *ad, double *result);
int calculateD(int fd, struct area_entry *ad, double *result);
int calculateF(int fd, struct area_entry *ad, double *result);
@@ -98,33 +111,35 @@
int calculate(int fd, struct area_entry *ad, double *result)
{
CELL *buf, *buf_sup, *buf_null;
- CELL corrCell;
- CELL precCell;
- CELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- int area_max = 0, area_min = 0;
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double rk = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ CELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = CELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_c_buf();
+ Rast_set_c_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -133,325 +148,198 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- buf_null = Rast_allocate_c_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
-
- /*the first time buf_sup is all null */
- Rast_set_c_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
- }
-
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
Rast_set_c_null_value(&precCell, 1);
- /* for each cell in the row */
- for (i = 0; i < ad->cl; i++) {
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
+ if (Rast_is_c_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&supCell, 1);
+ }
- supCell = buf_sup[i + ad->x];
+ if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) {
- /*first found patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
+ if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
}
- else {
- /* current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
-
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
+ connected = 1;
+ }
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
- }
- else {
- mask_patch_corr[i] = idCorr;
- }
- }
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
- }
-
- totCorr++;
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
- }
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_p;
+ double cell_size_m;
+ double min, max;
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot != 0) {
- if (array[i]->tot > area_max) {
- area_max = array[i]->tot;
- }
- if (array[i]->tot < area_min || area_min == 0) {
- area_min = array[i]->tot;
- }
+ /* get min and max patch size */
+ min = 1.0 / 0.0; /* inf */
+ max = -1.0 / 0.0; /* -inf */
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ if (min > area_p)
+ min = area_p;
+ if (max > area_p)
+ max = area_p;
}
}
-
- rk = area_max - area_min;
-
- indice = rk;
-
- G_free(array);
+ *result = max - min;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
@@ -459,33 +347,35 @@
int calculateD(int fd, struct area_entry *ad, double *result)
{
DCELL *buf, *buf_sup, *buf_null;
- DCELL corrCell;
- DCELL precCell;
- DCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- int area_max = 0, area_min = 0;
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double rk = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ DCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = DCELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_d_buf();
+ Rast_set_d_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -494,319 +384,203 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_d_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_d_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- for (j = 0; j < ad->rl; j++) {
- /*for each raster row */
- if (j > 0) {
- buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_d_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) {
- /* for each dcell in the row */
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
+ if (Rast_is_d_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&supCell, 1);
+ }
- supCell = buf_sup[i + ad->x];
+ if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first found patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
+ if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
}
- else {
- /* current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
-
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
+ connected = 1;
+ }
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
- }
- else {
- mask_patch_corr[i] = idCorr;
- }
- }
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
- }
-
- totCorr++;
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
- }
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double diff;
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot != 0) {
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
- if (array[i]->tot > area_max) {
- area_max = array[i]->tot;
- }
- if (array[i]->tot < area_min || area_min == 0) {
- area_min = array[i]->tot;
- }
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
-
- rk = area_max - area_min;
-
- indice = rk;
-
- G_free(array);
+ psd = sqrt(psd / npatch);
+ *result = psd;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
@@ -814,33 +588,35 @@
int calculateF(int fd, struct area_entry *ad, double *result)
{
FCELL *buf, *buf_sup, *buf_null;
- FCELL corrCell;
- FCELL precCell;
- FCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- int area_max = 0, area_min = 0;
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double rk = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ FCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = FCELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_f_buf();
+ Rast_set_f_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -849,318 +625,202 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_f_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_f_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_f_null_value(&precCell, 1);
- /* for each fcell in the row */
- for (i = 0; i < ad->cl; i++) {
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
+ if (Rast_is_f_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&supCell, 1);
+ }
- supCell = buf_sup[i + ad->x];
+ if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first found patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
+ if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
}
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
}
- else {
- /* current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
-
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
+ connected = 1;
+ }
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
- }
- else {
- mask_patch_corr[i] = idCorr;
- }
- }
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
- }
-
- totCorr++;
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
- }
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double diff;
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot != 0) {
- if (array[i]->tot > area_max) {
- area_max = array[i]->tot;
- }
- if (array[i]->tot < area_min || area_min == 0) {
- area_min = array[i]->tot;
- }
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
-
- rk = area_max - area_min;
-
- indice = rk;
-
- G_free(array);
+ psd = sqrt(psd / npatch);
+ *result = psd;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html
===================================================================
--- grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,7 +1,7 @@
<h2>DESCRIPTION</h2>
-<em>r.li.padrange</em> (patch area distribution range) calculates
-as:<br>
+<em>r.li.padrange</em> calculates the range of patch area sizes in
+hectares as:<br>
<img src="rlipadrange_formula.png" alt="rlipadrange formula"> <br>
with:<br>
<ul>
@@ -9,6 +9,10 @@
<li><b>a<small><small>min</small></small></b>: min patch area size</li>
</ul>
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells
+are ignored when tracing a patch.
+
<h2>NOTES</h2>
Do not use absolute path names for the <b>output</b> map/file.
@@ -16,14 +20,8 @@
output will be a raster map, otherwise an ASCII file will be generated in
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
-<!-- TODO: verify next: -->
-If the input raster map contains only NULL values then <em>r.li.padrange</em>
-returns -1.<br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+If the sample area contains only NULL values then <em>r.li.padrange</em>
+returns NULL.<br>
<h2>EXAMPLES</h2>
To calculate range of patch area size index on map <em>my_map</em>, using
@@ -51,8 +49,8 @@
Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
<h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
<p>
<i>Last changed: $Date$</i></p>
Modified: grass/trunk/raster/r.li/r.li.padsd/padsd.c
===================================================================
--- grass/trunk/raster/r.li/r.li.padsd/padsd.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padsd/padsd.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,28 +1,41 @@
-/*
- * \brief calculates standard deviation of patch area
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.padsd
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Fixes: Markus Neteler <neteler itc.it>
+ * Rewrite: Markus Metz
+ * Patch identification: Michael Shapiro - CERL
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- *
- */
+ * PURPOSE: calculates calculates standard deviation of patch areas
+ * COPYRIGHT: (C) 2007-2014 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/raster.h>
-#include <grass/glocale.h>
-
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
-#include "../r.li.daemon/GenericCell.h"
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
#include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+ long count;
+ generic_cell type;
+};
+
int calculate(int fd, struct area_entry *ad, double *result);
int calculateD(int fd, struct area_entry *ad, double *result);
int calculateF(int fd, struct area_entry *ad, double *result);
@@ -93,40 +106,39 @@
return RLI_OK;
}
+
int calculate(int fd, struct area_entry *ad, double *result)
{
CELL *buf, *buf_sup, *buf_null;
- CELL corrCell;
- CELL precCell;
- CELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- long npatch = 0;
- long np = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double somma = 0;
- double area = 0;
- double mn = 0;
- double sd = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ CELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = CELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_c_buf();
+ Rast_set_c_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -135,324 +147,203 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_c_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_c_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_c_null_value(&precCell, 1);
- /* for each cell in the row */
- for (i = 0; i < ad->cl; i++) {
- area++;
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_c_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) {
- /*first found patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
- }
- else {
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else { /*tree not null */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
- }
- }
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
+ if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else {
- mask_patch_corr[i] = idCorr;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
+ else {
+ pst[new_pid].count++;
}
-
- totCorr++;
}
+ connected = 1;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0) {
- doppi++;
- }
- }
- np = npatch;
- npatch = npatch - doppi;
- mn = areaPatch / npatch;
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double diff;
- /* calculate summary */
- for (i = 0; i < np; i++) {
- long areaPi = 0;
- double diff;
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (array[i]->tot != 0) {
- ris = ris + array[i]->tot;
- areaPi = (double)array[i]->tot;
- diff = areaPi - mn;
- somma = somma + (diff * diff);
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
+
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
- sd = sqrt(somma / npatch);
- indice = sd;
- G_free(array);
+ psd = sqrt(psd / npatch);
+ *result = psd;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
@@ -460,37 +351,35 @@
int calculateD(int fd, struct area_entry *ad, double *result)
{
DCELL *buf, *buf_sup, *buf_null;
- DCELL corrCell;
- DCELL precCell;
- DCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- long npatch = 0;
- long np = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- double indice = 0;
- double somma = 0;
- double area = 0;
- double mn = 0;
- double sd = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ DCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = DCELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_d_buf();
+ Rast_set_d_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -499,362 +388,239 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_d_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_d_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_d_null_value(&precCell, 1);
- /* for each dcell in the row */
- for (i = 0; i < ad->cl; i++) {
- area++;
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_d_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
- }
- else {
- /*current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else { /*tree not null */
+ if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
}
- }
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
-
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
-
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else {
- mask_patch_corr[i] = idCorr;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
+ else {
+ pst[new_pid].count++;
}
-
- totCorr++;
}
+ connected = 1;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0) {
- doppi++;
- }
- }
- np = npatch;
- npatch = npatch - doppi;
- mn = areaPatch / npatch;
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double diff;
- /* calculate summary */
- for (i = 0; i < np; i++) {
- long areaPi = 0;
- double diff;
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (array[i]->tot != 0) {
- ris = ris + array[i]->tot;
- areaPi = (double)array[i]->tot;
- diff = areaPi - mn;
- somma = somma + (diff * diff);
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
+
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
- sd = sqrt(somma / npatch);
- indice = sd;
- G_free(array);
+ psd = sqrt(psd / npatch);
+ *result = psd;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
+
int calculateF(int fd, struct area_entry *ad, double *result)
{
FCELL *buf, *buf_sup, *buf_null;
- FCELL corrCell;
- FCELL precCell;
- FCELL supCell;
- int i, j;
- int mask_fd = -1, *mask_buf = NULL;
- int ris = 0;
- int masked = FALSE;
- int areaPatch = 0; /*if all cells are null areaPatch=0 */
- long npatch = 0;
- long tot = 0;
- long zero = 0;
- long totCorr = 0;
- long idCorr = 0;
- long lastId = 0;
- long doppi = 0;
- long *mask_patch_sup;
- long *mask_patch_corr;
- long *ltmp;
- long np = 0;
- double indice = 0;
- double somma = 0;
- double area = 0;
- double mn = 0;
- double sd = 0;
- avlID_tree albero = NULL;
- avlID_table *array = NULL;
- generic_cell gc;
+ FCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
- gc.t = FCELL_TYPE;
+ Rast_get_cellhd(ad->raster, "", &hd);
+ buf_null = Rast_allocate_f_buf();
+ Rast_set_f_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
@@ -863,324 +629,202 @@
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
masked = TRUE;
}
- mask_patch_sup = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_sup == NULL) {
- G_fatal_error("malloc mask_patch_sup failed");
- return RLI_ERRORE;
- }
- mask_patch_corr = G_malloc(ad->cl * sizeof(long));
- if (mask_patch_corr == NULL) {
- G_fatal_error("malloc mask_patch_corr failed");
- return RLI_ERRORE;
- }
- buf_null = Rast_allocate_f_buf();
- if (buf_null == NULL) {
- G_fatal_error("malloc buf_null failed");
- return RLI_ERRORE;
- }
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
- /*the first time buf_sup is all null */
- Rast_set_f_null_value(buf_null, Rast_window_cols());
- buf_sup = buf_null;
- buf = buf_null;
-
- for (i = 0; i < ad->cl; i++) {
- mask_patch_sup[i] = 0;
- mask_patch_corr[i] = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
}
- /*for each raster row */
- for (j = 0; j < ad->rl; j++) {
- if (j > 0) {
- buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
}
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
if (masked) {
- if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
- G_fatal_error("mask read failed");
- return RLI_ERRORE;
- }
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
}
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
Rast_set_f_null_value(&precCell, 1);
- /* for each fcell in the row */
- for (i = 0; i < ad->cl; i++) {
- area++;
- corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, gc.t))) {
- areaPatch++;
- supCell = buf_sup[i + ad->x];
+ if (Rast_is_f_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&supCell, 1);
+ }
- if (corrCell != precCell) {
- /* ?
- * 1 2
- * */
- if (corrCell != supCell) {
- /* 3
- * 1 2
- * */
- /*new patch */
- if (idCorr == 0) { /*first patch */
- lastId = 1;
- idCorr = 1;
- totCorr = 1;
- mask_patch_corr[i] = idCorr;
- }
- else {
- /*not first patch */
- /* put in the tree the previous value */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- /*tree not empty */
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error
- ("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- totCorr = 1;
- lastId++;
- idCorr = lastId;
- mask_patch_corr[i] = idCorr;
- }
- }
- else {
- /*current cell and upper cell are equal */
- /* 2
- * 1 2
- * */
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else { /*tree not null */
+ if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
+ if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
- idCorr = mask_patch_sup[i];
- mask_patch_corr[i] = idCorr;
- totCorr = 1;
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
}
- }
- else { /*current cell and previuos cell are equal */
- /* ?
- * 1 1
- */
- if (corrCell == supCell) { /*current cell and upper cell are equal */
- /* 1
- * 1 1
- */
- if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
- long r = 0;
- long del = mask_patch_sup[i];
- r = avlID_sub(&albero, del); /*r=number of cell of patch removed */
-
- if (r == 0) {
- G_fatal_error("avlID_sub error");
- return RLI_ERRORE;
- }
-
- /*Remove one patch because it makes part of a patch already found */
- ris = avlID_add(&albero, idCorr, r);
-
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- r = i;
- while (r < ad->cl) {
- if (mask_patch_sup[r] == del) {
- mask_patch_sup[r] = idCorr;
- }
-
- r++;
- }
-
- mask_patch_corr[i] = idCorr;
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
- else {
- mask_patch_corr[i] = idCorr;
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
- else { /*current cell and upper cell are not equal */
- /* 2
- * 1 1
- */
- mask_patch_corr[i] = idCorr;
+ else {
+ pst[new_pid].count++;
}
-
- totCorr++;
}
+ connected = 1;
}
- else { /*cell is null or is not to consider */
- mask_patch_corr[i] = 0;
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
precCell = corrCell;
}
- ltmp = mask_patch_sup;
- mask_patch_sup = mask_patch_corr;
- mask_patch_corr = ltmp;
}
- if (areaPatch != 0) {
- if (albero == NULL) {
- albero = avlID_make(idCorr, totCorr);
- if (albero == NULL) {
- G_fatal_error("avlID_make error");
- return RLI_ERRORE;
- }
- npatch++;
- }
- else {
- ris = avlID_add(&albero, idCorr, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avlID_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- npatch++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avlID_add unknown error");
- return RLI_ERRORE;
- }
- }
- }
- array = G_malloc(npatch * sizeof(avlID_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avlID_to_array(albero, zero, array);
- if (tot != npatch) {
- G_warning
- ("avlID_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- for (i = 0; i < npatch; i++) {
- if (array[i]->tot == 0) {
- doppi++;
- }
- }
- np = npatch;
- npatch = npatch - doppi;
- mn = areaPatch / npatch;
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+ double area_p;
+ double cell_size_m;
+ double mps;
+ double psd;
+ double diff;
- /* calculate summary */
- for (i = 0; i < np; i++) {
- long areaPi = 0;
- double diff;
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (array[i]->tot != 0) {
- ris = ris + array[i]->tot;
- areaPi = (double)array[i]->tot;
- diff = areaPi - mn;
- somma = somma + (diff * diff);
+ cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+ area_units = cell_size_m * area;
+
+ /* mean patch size in hectares */
+ mps = area_units / (npatch * 10000);
+
+ /* calculate patch size standard deviation */
+ psd = 0;
+ for (old_pid = 1; old_pid <= pid; old_pid++) {
+ if (pst[old_pid].count > 0) {
+ area_p = cell_size_m * pst[old_pid].count / 10000;
+ diff = area_p - mps;
+ psd += diff * diff;
}
}
- sd = sqrt(somma / npatch);
- indice = sd;
- G_free(array);
+ psd = sqrt(psd / npatch);
+ *result = psd;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
if (masked) {
close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(mask_patch_sup);
- G_free(mask_patch_corr);
G_free(buf_null);
- avlID_destroy(albero);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
- *result = indice;
-
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html
===================================================================
--- grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,14 +1,19 @@
<h2>DESCRIPTION</h2>
-<em>r.li.padsd</em> (patch area distribution standard deviation) calculates as:<br>
+<em>r.li.padsd</em> calculates the standard deviation of patch
+area sizes in hectares as:<br>
<img src="rlipadsd_formula.png" alt="rlipadsd formula"> <br>
with:<br>
<ul>
<li><b>MPS</b>: mean patch area size</li>
<li><b>a<small><small>i</small></small></b>: area of patch i</li>
- <li><b>N<small>patch</small></b>: number of patch</li>
+ <li><b>N<small>patch</small></b>: number of patches</li>
</ul>
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells
+are ignored when tracing a patch.
+
<h2>NOTES</h2>
Do not use absolute path names for the <b>output</b> map/file.
@@ -16,14 +21,7 @@
output will be a raster map, otherwise an ASCII file will be generated in
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
-If input raster is not full of null values <em>r.li.padsd</em> returns a
-value >=0 that is PADsd. <br>
-If the input raster map contains only NULL values then <em>r.li.padsd</em> returns -1. <br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+The result is NULL if the sample area contains only NULL values.
<h2>EXAMPLES</h2>
To calculate patch area distribution standard deviation index on map <em>my_map</em>, using
@@ -50,8 +48,8 @@
Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
<h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.patchdensity/main.c
===================================================================
--- grass/trunk/raster/r.li/r.li.patchdensity/main.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchdensity/main.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -6,8 +6,11 @@
* students of Computer Science University of Pisa (Italy)
* Commission from Faunalia Pontedera (PI) www.faunalia.it
* Fixes: Serena Pallecchi, Markus Neteler <neteler itc.it>
+ * Rewrite: Markus Metz
+ * Patch identification: Michael Shapiro - CERL
+ *
* PURPOSE: calculates patch density index
- * COPYRIGHT: (C) 2006-2007 by the GRASS Development Team
+ * COPYRIGHT: (C) 2006-2014 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
@@ -21,7 +24,20 @@
#include <grass/raster.h>
#include <grass/glocale.h>
#include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+ long count;
+ generic_cell type;
+};
+
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
int main(int argc, char *argv[])
{
struct Option *raster, *conf, *output;
@@ -46,168 +62,716 @@
output = G_define_standard_option(G_OPT_R_OUTPUT);
- /** add other options for index parameters here */
-
if (G_parser(argc, argv))
exit(EXIT_FAILURE);
return calculateIndex(conf->answer, patch_density, NULL, raster->answer,
output->answer);
-
}
int patch_density(int fd, char **par, struct area_entry *ad, double *result)
{
- CELL *buf, *sup, *cnull;
- CELL pid, old_pid, *pid_curr, *pid_sup, *ctmp;
- int count, i, j, k, connected, other_above;
+ int ris = RLI_OK;
+ double indice = 0;
+
+ switch (ad->data_type) {
+ case CELL_TYPE:
+ {
+ calculate(fd, ad, &indice);
+ break;
+ }
+ case DCELL_TYPE:
+ {
+ calculateD(fd, ad, &indice);
+ break;
+ }
+ case FCELL_TYPE:
+ {
+ calculateF(fd, ad, &indice);
+ break;
+ }
+ default:
+ {
+ G_fatal_error("data type unknown");
+ return RLI_ERRORE;
+ }
+ }
+
+ if (ris != RLI_OK) {
+ return RLI_ERRORE;
+ }
+
+ *result = indice;
+
+ return RLI_OK;
+}
+
+
+int calculate(int fd, struct area_entry *ad, double *result)
+{
+ CELL *buf, *buf_sup, *buf_null;
+ CELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
struct Cell_head hd;
- int mask_fd, *mask_buf, null_count;
- double area;
- double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
Rast_get_cellhd(ad->raster, "", &hd);
- cnull = Rast_allocate_c_buf();
- Rast_set_c_null_value(cnull, Rast_window_cols());
- sup = cnull;
+ buf_null = Rast_allocate_c_buf();
+ Rast_set_c_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
/* initialize patch ids */
- pid_curr = Rast_allocate_c_buf();
- Rast_set_c_null_value(pid_curr, Rast_window_cols());
- pid_sup = Rast_allocate_c_buf();
- Rast_set_c_null_value(pid_sup, Rast_window_cols());
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
mask_fd = -1;
- mask_buf = NULL;
- null_count = 0;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
- return 0;
+ return RLI_ERRORE;
mask_buf = G_malloc(ad->cl * sizeof(int));
+ if (mask_buf == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
+ masked = TRUE;
}
- /* calculate distance */
- G_begin_distance_calculations();
- /* EW Dist at North edge */
- EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
- /* EW Dist at South Edge */
- EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
- /* NS Dist at East edge */
- NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
- /* NS Dist at West edge */
- NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
-
/* calculate number of patches */
- count = 0;
- connected = 0;
- other_above = 0;
+ npatch = 0;
+ area = 0;
pid = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
+ }
+
for (i = 0; i < ad->rl; i++) {
buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
if (i > 0) {
- sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
+ buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
}
- /* mask values */
- if (ad->mask == 1) {
+
+ if (masked) {
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
return 0;
- for (j = 0; j < ad->cl; j++) {
- if (mask_buf[j + ad->x] == 0) {
- Rast_set_c_null_value(&buf[j + ad->x], 1);
- null_count++;
+ }
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
+ Rast_set_c_null_value(&precCell, 1);
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&corrCell, 1);
+ }
+
+ if (Rast_is_c_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&supCell, 1);
+ }
+
+ if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
+
+ if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
+ }
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
+ }
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
+ }
+ else {
+ pst[new_pid].count++;
+ }
}
+ connected = 1;
}
+
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
+ }
+ precCell = corrCell;
}
+ }
+
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+
+ area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (ad->rl * ad->cl);
+
+ *result = (npatch / area_units) * 1000000;
+ }
+ else {
+ *result = 0;
+ }
+
+ if (masked) {
+ close(mask_fd);
+ G_free(mask_buf);
+ G_free(mask_sup);
+ }
+ G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
+
+ return RLI_OK;
+}
+
+
+int calculateD(int fd, struct area_entry *ad, double *result)
+{
+ DCELL *buf, *buf_sup, *buf_null;
+ DCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
+
+ Rast_get_cellhd(ad->raster, "", &hd);
+
+ buf_null = Rast_allocate_d_buf();
+ Rast_set_d_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
+ /* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
+ if (ad->mask == 1) {
+ if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+ return RLI_ERRORE;
+ mask_buf = G_malloc(ad->cl * sizeof(int));
+ if (mask_buf == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
+ masked = TRUE;
+ }
+
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
+
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
+ }
+
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
+ }
+
+ if (masked) {
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
+ }
- ctmp = pid_sup;
- pid_sup = pid_curr;
- pid_curr = ctmp;
- Rast_set_c_null_value(pid_curr, Rast_window_cols());
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+ Rast_set_d_null_value(&precCell, 1);
+
connected = 0;
- other_above = 1;
for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
- if (Rast_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&corrCell, 1);
+ }
+
+ if (Rast_is_d_null_value(&corrCell)) {
connected = 0;
- other_above = 1;
+ precCell = corrCell;
continue;
}
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&supCell, 1);
+ }
- if (sup[j + ad->x] == buf[j + ad->x]) {
-
- if (!connected) {
- pid_curr[j + ad->x] = pid_sup[j + ad->x];
- }
-
- if (pid_curr[j + ad->x] != pid_sup[j + ad->x]) {
+ if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
+
+ if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
if (connected) {
- count--;
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
}
- if (other_above) {
- pid_curr[j + ad->x] = pid_sup[j + ad->x];
- for (k = j + ad->x - 1; k >= ad->x; k--) {
- if (buf[k] != buf[j + ad->x])
- break;
- pid_curr[k] = pid_sup[j + ad->x];
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
+ }
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
else {
- old_pid = pid_sup[j + ad->x];
- pid_sup[j + ad->x] = pid_curr[j + ad->x];
+ pst[new_pid].count++;
+ }
+ }
+ connected = 1;
+ }
+
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
+ }
+ precCell = corrCell;
+ }
+ }
+
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
+
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+
+ area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (ad->rl * ad->cl);
+
+ *result = (npatch / area_units) * 1000000;
+ }
+ else {
+ *result = 0;
+ }
+
+ if (masked) {
+ close(mask_fd);
+ G_free(mask_buf);
+ G_free(mask_sup);
+ }
+ G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
+
+ return RLI_OK;
+}
+
+
+int calculateF(int fd, struct area_entry *ad, double *result)
+{
+ FCELL *buf, *buf_sup, *buf_null;
+ FCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
+
+ Rast_get_cellhd(ad->raster, "", &hd);
+
+ buf_null = Rast_allocate_f_buf();
+ Rast_set_f_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
+ /* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
+ if (ad->mask == 1) {
+ if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+ return RLI_ERRORE;
+ mask_buf = G_malloc(ad->cl * sizeof(int));
+ if (mask_buf == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
+ masked = TRUE;
+ }
+
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
+
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
+ }
+
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
+ }
+
+ if (masked) {
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
+ }
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
+ Rast_set_f_null_value(&precCell, 1);
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&corrCell, 1);
+ }
+
+ if (Rast_is_f_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&supCell, 1);
+ }
+
+ if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
+
+ if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
+ }
+ /* update right side of the previous row */
for (k = j + 1; k < ad->cl; k++) {
- if (pid_sup[k + ad->x] == old_pid) {
- pid_sup[k + ad->x] = pid_curr[j + ad->x];
- }
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
-
- other_above = 0;
connected = 1;
}
if (!connected) {
- count++;
+ /* start new patch */
+ npatch++;
pid++;
- pid_curr[j + ad->x] = pid;
- }
+ pid_corr[j + ad->x] = pid;
- if (j < ad->cl - 1) {
- if (buf[j + ad->x] == buf[j + 1 + ad->x]) {
-
- connected = 1;
- pid_curr[j + 1 + ad->x] = pid_curr[j + ad->x];
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
- else {
- other_above = 1;
- connected = 0;
- }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
+ precCell = corrCell;
}
}
- area = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
- (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) *
- (ad->rl *ad->cl - null_count);
+ if (npatch > 0) {
+ double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+ double area_units;
- if (area != 0)
- *result = (count / area) * 1000000;
- else
- Rast_set_d_null_value(result, 1);
+ /* calculate distance */
+ G_begin_distance_calculations();
+ /* EW Dist at North edge */
+ EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+ /* EW Dist at South Edge */
+ EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+ /* NS Dist at East edge */
+ NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+ /* NS Dist at West edge */
+ NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
- if (ad->mask == 1) {
+ area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+ (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (ad->rl * ad->cl);
+
+ *result = (npatch / area_units) * 1000000;
+ }
+ else {
+ *result = 0;
+ }
+
+ if (masked) {
+ close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
-
- G_free(cnull);
- G_free(pid_curr);
+ G_free(buf_null);
+ G_free(pid_corr);
G_free(pid_sup);
+ G_free(pst);
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html
===================================================================
--- grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,11 +1,17 @@
<h2>DESCRIPTION</h2>
-<em>r.li.patchdensity</em> calculates the "patch density index" as:
+<em>r.li.patchdensity</em> calculates the "patch density index",
+the number of patches per square kilometer, as:
<div class="code"><pre>
-f(sample_area) = (Patch_Number/Area) * 1000000
+PD = (Npatch / A) * 1000000
</pre></div>
-that is the number of patches per 1,000,000 area units.
+with:
+<ul>
+ <li><b>A</b>:sampling area size</li>
+ <li><b>Npatch</b>: number of patches</li>
+</ul>
+
<p>
This index is calculated using a 4 neighbour algorithm, diagonal cells
are ignored when tracing a patch.
@@ -17,16 +23,8 @@
output will be a raster map, otherwise an ASCII file will be generated in
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
-<!-- TODO: verify next: -->
-A map of NULL values is considered to have zero patches. <br>
-If the size of the sample area is 0, <em>r.li.patchdensity</em> returns
-NULL. This is only possible if the raster is masked.<br>
-If you want to change these NULL values to some number, run subsequently
-on the resulting map:
-<div class="code"><pre>
-r.null null=-1 input=my_out
-</pre></div>
-after index calculation.
+A sample area of only NULL values is considered to have zero patches,
+that is, the result is always ≥ 0.
<h2>EXAMPLES</h2>
To calculate patch density index on map <em>my_map</em>, using
@@ -64,10 +62,8 @@
Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
<h2>AUTHORS</h2>
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
-Claudio Porta and Lucio Davide Spano, students of Computer Science
-University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI) (www.faunalia.it)<br>
-
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.patchnum/main.c
===================================================================
--- grass/trunk/raster/r.li/r.li.patchnum/main.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchnum/main.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -6,9 +6,11 @@
* students of Computer Science University of Pisa (Italy)
* Commission from Faunalia Pontedera (PI) www.faunalia.it
* Fixes: Markus Neteler <neteler itc.it>
+ * Rewrite: Markus Metz
+ * Patch identification: Michael Shapiro - CERL
*
* PURPOSE: calculates patch number index
- * COPYRIGHT: (C) 2007-2007 by the GRASS Development Team
+ * COPYRIGHT: (C) 2007-2014 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
@@ -22,8 +24,20 @@
#include <grass/raster.h>
#include <grass/glocale.h>
#include "../r.li.daemon/daemon.h"
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/GenericCell.h"
+/* template for patch density, mps, padcv, padrange, padsd */
+
+/* cell count and type of each patch */
+struct pst {
+ long count;
+ generic_cell type;
+};
+
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
int main(int argc, char *argv[])
{
struct Option *raster, *conf, *output;
@@ -48,145 +62,649 @@
output = G_define_standard_option(G_OPT_R_OUTPUT);
-
if (G_parser(argc, argv))
exit(EXIT_FAILURE);
return calculateIndex(conf->answer, patch_number, NULL, raster->answer,
output->answer);
-
}
int patch_number(int fd, char **par, struct area_entry *ad, double *result)
{
- CELL *buf, *sup, *cnull;
- CELL pid, old_pid, *pid_curr, *pid_sup, *ctmp;
- int count, i, j, k, connected, other_above;
+ int ris = RLI_OK;
+ double indice = 0;
+
+ switch (ad->data_type) {
+ case CELL_TYPE:
+ {
+ calculate(fd, ad, &indice);
+ break;
+ }
+ case DCELL_TYPE:
+ {
+ calculateD(fd, ad, &indice);
+ break;
+ }
+ case FCELL_TYPE:
+ {
+ calculateF(fd, ad, &indice);
+ break;
+ }
+ default:
+ {
+ G_fatal_error("data type unknown");
+ return RLI_ERRORE;
+ }
+ }
+
+ if (ris != RLI_OK) {
+ return RLI_ERRORE;
+ }
+
+ *result = indice;
+
+ return RLI_OK;
+}
+
+
+int calculate(int fd, struct area_entry *ad, double *result)
+{
+ CELL *buf, *buf_sup, *buf_null;
+ CELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
struct Cell_head hd;
- int mask_fd, *mask_buf, null_count;
Rast_get_cellhd(ad->raster, "", &hd);
- cnull = Rast_allocate_c_buf();
- Rast_set_c_null_value(cnull, Rast_window_cols());
- sup = cnull;
+ buf_null = Rast_allocate_c_buf();
+ Rast_set_c_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
/* initialize patch ids */
- pid_curr = Rast_allocate_c_buf();
- Rast_set_c_null_value(pid_curr, Rast_window_cols());
- pid_sup = Rast_allocate_c_buf();
- Rast_set_c_null_value(pid_sup, Rast_window_cols());
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
/* open mask if needed */
mask_fd = -1;
- mask_buf = NULL;
- null_count = 0;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
- return 0;
+ return RLI_ERRORE;
mask_buf = G_malloc(ad->cl * sizeof(int));
+ if (mask_buf == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
+ masked = TRUE;
}
/* calculate number of patches */
- count = 0;
- connected = 0;
- other_above = 0;
+ npatch = 0;
+ area = 0;
pid = 0;
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
+ }
+
for (i = 0; i < ad->rl; i++) {
buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
if (i > 0) {
- sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
+ buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
}
- /* mask values */
- if (ad->mask == 1) {
+
+ if (masked) {
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
return 0;
- for (j = 0; j < ad->cl; j++) {
- if (mask_buf[j + ad->x] == 0) {
- Rast_set_c_null_value(&buf[j + ad->x], 1);
- null_count++;
+ }
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
+ Rast_set_c_null_value(&precCell, 1);
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&corrCell, 1);
+ }
+
+ if (Rast_is_c_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_c_null_value(&supCell, 1);
+ }
+
+ if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
+
+ if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
+ }
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
+ }
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
+ }
+ else {
+ pst[new_pid].count++;
+ }
}
+ connected = 1;
}
+
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
+ }
+ precCell = corrCell;
}
+ }
+
+ *result = npatch;
+
+ if (masked) {
+ close(mask_fd);
+ G_free(mask_buf);
+ G_free(mask_sup);
+ }
+ G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
+
+ return RLI_OK;
+}
+
+
+int calculateD(int fd, struct area_entry *ad, double *result)
+{
+ DCELL *buf, *buf_sup, *buf_null;
+ DCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
+
+ Rast_get_cellhd(ad->raster, "", &hd);
+
+ buf_null = Rast_allocate_d_buf();
+ Rast_set_d_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
+ /* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
+ if (ad->mask == 1) {
+ if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+ return RLI_ERRORE;
+ mask_buf = G_malloc(ad->cl * sizeof(int));
+ if (mask_buf == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
+ masked = TRUE;
+ }
+
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
+
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
+ }
+
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
+ }
+
+ if (masked) {
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
+ }
- ctmp = pid_sup;
- pid_sup = pid_curr;
- pid_curr = ctmp;
- Rast_set_c_null_value(pid_curr, Rast_window_cols());
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+ Rast_set_d_null_value(&precCell, 1);
+
connected = 0;
- other_above = 1;
for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
- if (Rast_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&corrCell, 1);
+ }
+
+ if (Rast_is_d_null_value(&corrCell)) {
connected = 0;
- other_above = 1;
+ precCell = corrCell;
continue;
}
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_d_null_value(&supCell, 1);
+ }
- if (sup[j + ad->x] == buf[j + ad->x]) {
-
- if (!connected) {
- pid_curr[j + ad->x] = pid_sup[j + ad->x];
- }
-
- if (pid_curr[j + ad->x] != pid_sup[j + ad->x]) {
+ if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
+
+ if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
if (connected) {
- count--;
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
}
- if (other_above) {
- pid_curr[j + ad->x] = pid_sup[j + ad->x];
- for (k = j + ad->x - 1; k >= ad->x; k--) {
- if (buf[k] != buf[j + ad->x])
- break;
- pid_curr[k] = pid_sup[j + ad->x];
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
}
+ /* update right side of the previous row */
+ for (k = j + 1; k < ad->cl; k++) {
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
+ }
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
else {
- old_pid = pid_sup[j + ad->x];
- pid_sup[j + ad->x] = pid_curr[j + ad->x];
+ pst[new_pid].count++;
+ }
+ }
+ connected = 1;
+ }
+
+ if (!connected) {
+ /* start new patch */
+ npatch++;
+ pid++;
+ pid_corr[j + ad->x] = pid;
+
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+ nalloc = pid + incr;
+ }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
+ }
+ precCell = corrCell;
+ }
+ }
+
+ *result = npatch;
+
+ if (masked) {
+ close(mask_fd);
+ G_free(mask_buf);
+ G_free(mask_sup);
+ }
+ G_free(buf_null);
+ G_free(pid_corr);
+ G_free(pid_sup);
+ G_free(pst);
+
+ return RLI_OK;
+}
+
+
+int calculateF(int fd, struct area_entry *ad, double *result)
+{
+ FCELL *buf, *buf_sup, *buf_null;
+ FCELL corrCell, precCell, supCell;
+ long npatch, area;
+ long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+ struct pst *pst;
+ long nalloc, incr;
+ int i, j, k;
+ int connected;
+ int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+ struct Cell_head hd;
+
+ Rast_get_cellhd(ad->raster, "", &hd);
+
+ buf_null = Rast_allocate_f_buf();
+ Rast_set_f_null_value(buf_null, Rast_window_cols());
+ buf_sup = buf_null;
+
+ /* initialize patch ids */
+ pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+ pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+ for (j = 0; j < Rast_window_cols(); j++) {
+ pid_corr[j] = 0;
+ pid_sup[j] = 0;
+ }
+
+ /* open mask if needed */
+ mask_fd = -1;
+ mask_buf = mask_sup = NULL;
+ masked = FALSE;
+ if (ad->mask == 1) {
+ if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+ return RLI_ERRORE;
+ mask_buf = G_malloc(ad->cl * sizeof(int));
+ if (mask_buf == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ mask_sup = G_malloc(ad->cl * sizeof(int));
+ if (mask_sup == NULL) {
+ G_fatal_error("malloc mask_buf failed");
+ return RLI_ERRORE;
+ }
+ for (j = 0; j < ad->cl; j++)
+ mask_buf[j] = 0;
+
+ masked = TRUE;
+ }
+
+ /* calculate number of patches */
+ npatch = 0;
+ area = 0;
+ pid = 0;
+
+ /* patch size and type */
+ incr = 1024;
+ if (incr > ad->rl)
+ incr = ad->rl;
+ if (incr > ad->cl)
+ incr = ad->cl;
+ if (incr < 2)
+ incr = 2;
+ nalloc = incr;
+ pst = G_malloc(nalloc * sizeof(struct pst));
+ for (k = 0; k < nalloc; k++) {
+ pst[k].count = 0;
+ }
+
+ for (i = 0; i < ad->rl; i++) {
+ buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+ if (i > 0) {
+ buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
+ }
+
+ if (masked) {
+ mask_tmp = mask_sup;
+ mask_sup = mask_buf;
+ mask_buf = mask_tmp;
+ if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+ return 0;
+ }
+
+ ltmp = pid_sup;
+ pid_sup = pid_corr;
+ pid_corr = ltmp;
+
+ Rast_set_f_null_value(&precCell, 1);
+
+ connected = 0;
+ for (j = 0; j < ad->cl; j++) {
+ pid_corr[j + ad->x] = 0;
+
+ corrCell = buf[j + ad->x];
+ if (masked && (mask_buf[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&corrCell, 1);
+ }
+
+ if (Rast_is_f_null_value(&corrCell)) {
+ connected = 0;
+ precCell = corrCell;
+ continue;
+ }
+
+ area++;
+
+ supCell = buf_sup[j + ad->x];
+ if (masked && (mask_sup[j + ad->x] == 0)) {
+ Rast_set_f_null_value(&supCell, 1);
+ }
+
+ if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
+ pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+ connected = 1;
+ pst[pid_corr[j + ad->x]].count++;
+ }
+ else {
+ connected = 0;
+ }
+
+ if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
+
+ if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+ /* connect or merge */
+ /* after r.clump */
+ if (connected) {
+ npatch--;
+
+ if (npatch == 0) {
+ G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+ }
+ }
+
+ old_pid = pid_corr[j + ad->x];
+ new_pid = pid_sup[j + ad->x];
+ pid_corr[j + ad->x] = new_pid;
+ if (old_pid > 0) {
+ /* merge */
+ /* update left side of the current row */
+ for (k = 0; k < j; k++) {
+ if (pid_corr[k + ad->x] == old_pid)
+ pid_corr[k + ad->x] = new_pid;
+ }
+ /* update right side of the previous row */
for (k = j + 1; k < ad->cl; k++) {
- if (pid_sup[k + ad->x] == old_pid) {
- pid_sup[k + ad->x] = pid_curr[j + ad->x];
- }
+ if (pid_sup[k + ad->x] == old_pid)
+ pid_sup[k + ad->x] = new_pid;
}
+ pst[new_pid].count += pst[old_pid].count;
+ pst[old_pid].count = 0;
+
+ if (old_pid == pid)
+ pid--;
}
+ else {
+ pst[new_pid].count++;
+ }
}
-
- other_above = 0;
connected = 1;
}
if (!connected) {
- count++;
+ /* start new patch */
+ npatch++;
pid++;
- pid_curr[j + ad->x] = pid;
- }
+ pid_corr[j + ad->x] = pid;
- if (j < ad->cl - 1) {
- if (buf[j + ad->x] == buf[j + 1 + ad->x]) {
-
- connected = 1;
- pid_curr[j + 1 + ad->x] = pid_curr[j + ad->x];
+ if (pid >= nalloc) {
+ pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+ for (k = nalloc; k < pid + incr; k++)
+ pst[k].count = 0;
+
+ nalloc = pid + incr;
}
- else {
- other_above = 1;
- connected = 0;
- }
+
+ pst[pid].count = 1;
+ pst[pid].type.t = CELL_TYPE;
+ pst[pid].type.val.c = corrCell;
}
+ precCell = corrCell;
}
}
- *result = count;
+ *result = npatch;
- if (ad->mask == 1) {
+ if (masked) {
+ close(mask_fd);
G_free(mask_buf);
+ G_free(mask_sup);
}
- G_free(cnull);
- G_free(pid_curr);
+ G_free(buf_null);
+ G_free(pid_corr);
G_free(pid_sup);
+ G_free(pst);
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html
===================================================================
--- grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html 2014-02-17 10:05:22 UTC (rev 59072)
@@ -2,8 +2,11 @@
<em>r.li.patchnum</em> calculates the "patch number index" as:<br>
<I> f(sample_area)= Patch_Number </I><br>
-This index is calculated using a 4 neighbour algorithm<br>
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells
+are ignored when tracing a patch.
+
<h2>NOTES</h2>
Do not use absolute path names for the <b>output</b> map/file.
@@ -11,13 +14,8 @@
output will be a raster map, otherwise an ASCII file will be generated in
the <tt>$HOME/.grass7/r.li/output/</tt> folder.
<p>
-<!-- TODO verify: -->
-If the input raster map contains only NULL values then it is considered to have zero patch. <br>
-If you want to keep NULL values, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=0 input=my_map
-</pre></div>
-after index calculation.
+If the sample area contains only NULL values then it is considered to
+have zero patches. <br>
<h2>EXAMPLES</h2>
To calculate patch number index on map <em>my_map</em>, using
@@ -45,9 +43,8 @@
Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
<h2>AUTHORS</h2>
-Claudio Porta and Lucio Davide Spano, students of Computer Science
-University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI) (www.faunalia.it)<br>
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
<p>
<i>Last changed: $Date$</i>
Modified: grass/trunk/raster/r.li/r.li.pielou/pielou.c
===================================================================
--- grass/trunk/raster/r.li/r.li.pielou/pielou.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.pielou/pielou.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -7,6 +7,7 @@
*
* AUTHOR(S): Luca Delucchi, Fondazione Edmund Mach
* Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ * Rewrite: Markus Metz
*
* COPYRIGHT:
* This program is free software under the GPL (>=v2)
@@ -14,41 +15,27 @@
*
***************************************************************************/
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
#include "../r.li.daemon/avlDefs.h"
#include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
+/* template is shannon */
+
int calculate(int fd, struct area_entry *ad, double *result);
-
int calculateD(int fd, struct area_entry *ad, double *result);
-
int calculateF(int fd, struct area_entry *ad, double *result);
-/*This function is used to sort the values in the moving window */
-static int cmp(const void *pa, const void *pb)
-{
- double *p1 = (double *)pa;
- double *p2 = (double *)pb;
-
- if (*p1 < *p2)
- return -1;
- if (*p1 > *p2)
- return 1;
- return 0;
-}
-
int main(int argc, char *argv[])
{
struct Option *raster, *conf, *output;
-
struct GModule *module;
G_gisinit(argv[0]);
@@ -75,18 +62,13 @@
return calculateIndex(conf->answer, pielou, NULL, raster->answer,
output->answer);
-
}
int pielou(int fd, char **par, struct area_entry *ad, double *result)
{
-
int ris = RLI_OK;
double indice = 0;
- struct Cell_head hd;
- Rast_get_cellhd(ad->raster, "", &hd);
-
switch (ad->data_type) {
case CELL_TYPE:
{
@@ -117,7 +99,6 @@
*result = indice;
return RLI_OK;
-
}
@@ -125,48 +106,31 @@
{
CELL *buf;
CELL corrCell;
+ CELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- /* add to compute the number of class */
- double *array_copy;
- int totNumClass = 1;
- double logTotNumClass;
-
- generic_cell cc;
- generic_cell cc_passage; /*add to compute the number of class */
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = CELL_TYPE;
+ uc.t = CELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
- mask_buf = G_malloc(Rast_window_cols() * sizeof(int));
+ mask_buf = G_malloc(ad->cl * sizeof(int));
if (mask_buf == NULL) {
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
@@ -174,10 +138,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -185,31 +146,42 @@
}
}
+ buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+ Rast_set_c_null_value(&precCell, 1);
+
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.c = corrCell;
- albero = avl_make(cc, 1);
-
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.c = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -227,72 +199,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
- }
- } /* end for */
- } /* end for */
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
/*last closing */
- if (a != 0 && albero != NULL) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+ m++;
+ }
+ else {
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
+ }
- array = G_malloc(m * sizeof(AVL_tableRow *));
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
+ array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
- array_copy = G_malloc(m * sizeof(double));
- for (i = 0; i < m; i++) {
- cc_passage = array[i]->k;
- array_copy[i] = cc_passage.val.c;
- }
-
- qsort(array_copy, m, sizeof(double), cmp);
-
- for (i = 1; i < m; i++) {
- if (array_copy[i - 1] != array_copy[i]) {
- totNumClass++;
- }
- }
-
G_free(array);
- G_free(array_copy);
- logTotNumClass = (double)log(totNumClass);
- indice = ((-1) * somma) / logTotNumClass;
-
- G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
- somma, logTotNumClass, indice);
+ *result = -shannon / log(m);
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
@@ -302,43 +293,26 @@
{
DCELL *buf;
DCELL corrCell;
+ DCELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- /* add to compute the number of class */
- double *array_copy;
- int totNumClass = 1;
- double logTotNumClass;
-
- generic_cell cc;
- generic_cell cc_passage; /*add to compute the number of class */
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = DCELL_TYPE;
+ uc.t = DCELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -351,10 +325,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -362,30 +333,42 @@
}
}
- for (i = 0; i < ad->cl; i++) { /* for each dcell in the row */
- area++;
+ buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_d_null_value(&precCell, 1);
+
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.dc = corrCell;
- albero = avl_make(cc, 1);
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.dc = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -403,72 +386,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
+
+ /*last closing */
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
}
- } /*close for */
- } /*close for */
+ m++;
+ }
+ else {
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
+ }
- /*last closing */
- if (a != 0 && albero != NULL) {
- array = G_malloc(m * sizeof(AVL_tableRow *));
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
+ array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning
- ("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
- array_copy = G_malloc(m * sizeof(double));
- for (i = 0; i < m; i++) {
- cc_passage = array[i]->k;
- array_copy[i] = cc_passage.val.c;
- }
-
- qsort(array_copy, m, sizeof(double), cmp);
-
- for (i = 1; i < m; i++) {
- if (array_copy[i - 1] != array_copy[i]) {
- totNumClass++;
- }
- }
-
G_free(array);
- G_free(array_copy);
- logTotNumClass = (double)log(totNumClass);
- indice = ((-1) * somma) / logTotNumClass;
-
- G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
- somma, logTotNumClass, indice);
+ *result = -shannon / log(m);
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
@@ -478,43 +480,26 @@
{
FCELL *buf;
FCELL corrCell;
+ FCELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- /* add to compute the number of class */
- double *array_copy;
- int totNumClass = 1;
- double logTotNumClass;
-
- generic_cell cc;
- generic_cell cc_passage; /*add to compute the number of class */
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = FCELL_TYPE;
+ uc.t = FCELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -527,10 +512,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -538,29 +520,42 @@
}
}
- for (i = 0; i < ad->cl; i++) { /* for each fcell in the row */
- area++;
+ buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_f_null_value(&precCell, 1);
+
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.fc = corrCell;
- albero = avl_make(cc, 1);
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.fc = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -578,71 +573,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
+
+ /*last closing */
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
}
+ m++;
}
+ else {
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
}
- /*last closing */
- if (a != 0 && albero != NULL) {
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
- array_copy = G_malloc(m * sizeof(double));
- for (i = 0; i < m; i++) {
- cc_passage = array[i]->k;
- array_copy[i] = cc_passage.val.c;
- }
-
- qsort(array_copy, m, sizeof(double), cmp);
-
- for (i = 1; i < m; i++) {
- if (array_copy[i - 1] != array_copy[i]) {
- totNumClass++;
- }
- }
-
G_free(array);
- G_free(array_copy);
- logTotNumClass = (double)log(totNumClass);
- indice = ((-1) * somma) / logTotNumClass;
-
- G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
- somma, logTotNumClass, indice);
+ *result = -shannon / log(m);
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.renyi/renyi.c
===================================================================
--- grass/trunk/raster/r.li/r.li.renyi/renyi.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.renyi/renyi.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -7,6 +7,7 @@
*
* AUTHOR(S): Luca Delucchi, Fondazione Edmund Mach
* Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ * Rewrite: Markus Metz
*
* COPYRIGHT:
* This program is free software under the GPL (>=v2)
@@ -21,15 +22,14 @@
#include <grass/gis.h>
#include <grass/glocale.h>
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
#include "../r.li.daemon/avlDefs.h"
#include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
-double calculate(struct area_entry *ad, int fd, char **par, double *result);
+/* template is shannon */
+double calculate(struct area_entry *ad, int fd, char **par, double *result);
double calculateD(struct area_entry *ad, int fd, char **par, double *result);
-
double calculateF(struct area_entry *ad, int fd, char **par, double *result);
int main(int argc, char *argv[])
@@ -82,17 +82,15 @@
}
return calculateIndex(conf->answer, renyi, par, raster->answer,
output->answer);
-
}
int renyi(int fd, char **par, struct area_entry *ad, double *result)
{
-
int ris = RLI_OK;
double indice = 0;
- struct Cell_head hd;
- Rast_get_cellhd(ad->raster, "", &hd);
+ if (!par)
+ G_fatal_error("par is NULL");
switch (ad->data_type) {
case CELL_TYPE:
@@ -124,37 +122,28 @@
*result = indice;
return RLI_OK;
-
}
-
-double calculate(struct area_entry *ad, int fd, char **par, double *result)
+int calculate(int fd, struct area_entry *ad, double *result)
{
-
CELL *buf;
CELL corrCell;
CELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
- long totCorr = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double p = 0;
- double area = 0;
- double t;
+ long area = 0;
avl_tree albero = NULL;
-
AVL_table *array;
generic_cell uc;
@@ -172,10 +161,6 @@
masked = TRUE;
}
-
- Rast_set_c_null_value(&precCell, 1);
-
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -185,71 +170,71 @@
}
buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+ Rast_set_c_null_value(&precCell, 1);
+
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf[i + ad->x];
if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, uc.t))) {
- a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
+ area++;
+ }
- if (corrCell != precCell) {
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
+ if (albero == NULL) {
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
- uc.val.c = precCell;
- albero = avl_make(uc, totCorr);
- if (albero == NULL) {
- G_fatal_error("avl_make error");
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+
+ m++;
+ }
+ else {
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
return RLI_ERRORE;
}
- else
+ case AVL_ADD:
+ {
m++;
- }
- else {
- uc.val.c = precCell;
- ris = avl_add(&albero, uc, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avl_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- m++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avl_make unknown error");
- return RLI_ERRORE;
- }
+ break;
}
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_make unknown error");
+ return RLI_ERRORE;
+ }
}
- totCorr = 1;
- } /* endif not equal cells */
- else { /*equal cells */
-
- totCorr++;
}
- precCell = corrCell;
- }
-
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.c = precCell;
albero = avl_make(uc, totCorr);
@@ -285,69 +270,68 @@
}
}
}
- array = G_malloc(m * sizeof(AVL_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avl_to_array(albero, zero, array);
- if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- char *sval;
+ if (area > 0) {
+ double alpha;
+ double pi;
+ double t;
+ double sum;
- sval = par[0];
- double alpha_double;
+ alpha = atof(par[0]);
- alpha_double = (double)atof(sval);
- /* claculate index summary */
- for (i = 0; i < m; i++) {
- t = (double)(array[i]->tot);
- p = t / area;
- G_debug(1, "Valore p: %g, valore pow: %g", p, pow(p, alpha_double));
- somma = somma + pow(p, alpha_double);
- }
+ array = G_malloc(m * sizeof(AVL_tableRow));
+ if (array == NULL) {
+ G_fatal_error("malloc array failed");
+ return RLI_ERRORE;
+ }
+ tot = avl_to_array(albero, zero, array);
+ if (tot != m) {
+ G_warning("avl_to_array unexpected value. the result could be wrong");
+ return RLI_ERRORE;
+ }
- indice = (1 / (1 - alpha_double)) * log(somma);
- if (isnan(indice) || isinf(indice)) {
- indice = -1;
+ /* calculate renyi index */
+ sum = 0;
+ for (i = 0; i < m; i++) {
+ t = array[i]->tot;
+ pi = t / area;
+ sum += pow(pi, alpha);
+ }
+ G_free(array);
+
+ *result = (1 / (1 - alpha)) * log(sum);
}
- G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
+ else
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
-
- G_free(array);
- if (masked)
+ avl_destroy(albero);
+ if (masked) {
+ close(mask_fd);
G_free(mask_buf);
+ }
return RLI_OK;
}
-double calculateD(struct area_entry *ad, int fd, char **par, double *result)
+int calculateD(int fd, struct area_entry *ad, double *result)
{
DCELL *buf;
DCELL corrCell;
DCELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
+
long m = 0;
long tot = 0;
long zero = 0;
- long totCorr = 0;
- double indice = 0;
- double somma = 0;
- double p = 0;
- double area = 0;
- double t;
+ long totCorr = 1;
+ long area = 0;
+
avl_tree albero = NULL;
AVL_table *array;
generic_cell uc;
@@ -360,14 +344,12 @@
return RLI_ERRORE;
mask_buf = G_malloc(ad->cl * sizeof(int));
if (mask_buf == NULL) {
- G_fatal_error("malloc mask_buffailed");
+ G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
masked = TRUE;
}
- Rast_set_d_null_value(&precCell, 1);
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -377,72 +359,71 @@
}
buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_d_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) { /* for each dcell in the row */
- area++;
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, uc.t))) {
- a = 1;
+ area++;
+ }
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
- if (corrCell != precCell) {
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
+ if (albero == NULL) {
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
- uc.val.dc = precCell;
- albero = avl_make(uc, totCorr);
- if (albero == NULL) {
- G_fatal_error("avl_make error");
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+
+ m++;
+ }
+ else {
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
return RLI_ERRORE;
}
- m++;
- }
- else {
- uc.val.dc = precCell;
- ris = avl_add(&albero, uc, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avl_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- m++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avl_make unknown error");
- return RLI_ERRORE;
- }
+ case AVL_ADD:
+ {
+ m++;
+ break;
}
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_make unknown error");
+ return RLI_ERRORE;
+ }
}
- totCorr = 1;
- } /* endif not equal dcells */
- else { /*equal dcells */
-
- totCorr++;
}
- precCell = corrCell;
- }
-
-
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.dc = precCell;
albero = avl_make(uc, totCorr);
@@ -479,76 +460,68 @@
}
}
- array = G_malloc(m * sizeof(AVL_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avl_to_array(albero, zero, array);
+ if (area > 0) {
+ double alpha;
+ double pi;
+ double t;
+ double sum;
- if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
+ alpha = atof(par[0]);
- char *sval;
+ array = G_malloc(m * sizeof(AVL_tableRow));
+ if (array == NULL) {
+ G_fatal_error("malloc array failed");
+ return RLI_ERRORE;
+ }
+ tot = avl_to_array(albero, zero, array);
+ if (tot != m) {
+ G_warning("avl_to_array unexpected value. the result could be wrong");
+ return RLI_ERRORE;
+ }
- sval = par[0];
- double alpha_double;
-
- alpha_double = (double)atof(sval);
- /* claculate index summary */
- for (i = 0; i < m; i++) {
- t = (double)(array[i]->tot);
- p = t / area;
- G_debug(1, "Valore p: %g, valore pow: %g", p, pow(p, alpha_double));
- somma = somma + pow(p, alpha_double);
+ /* calculate renyi index */
+ sum = 0;
+ for (i = 0; i < m; i++) {
+ t = array[i]->tot;
+ pi = t / area;
+ sum += pow(pi, alpha);
+ }
+ G_free(array);
+
+ *result = (1 / (1 - alpha)) * log(sum);
}
+ else
+ Rast_set_d_null_value(result, 1);
- indice = (1 / (1 - alpha_double)) * log(somma);
-
- if (isnan(indice) || isinf(indice)) {
- indice = -1;
+ avl_destroy(albero);
+ if (masked) {
+ close(mask_fd);
+ G_free(mask_buf);
}
- G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
-
- *result = indice;
-
- G_free(array);
- if (masked)
- G_free(mask_buf);
-
return RLI_OK;
}
-
-double calculateF(struct area_entry *ad, int fd, char **par, double *result)
+int calculateF(int fd, struct area_entry *ad, double *result)
{
FCELL *buf;
FCELL corrCell;
FCELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
- long totCorr = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double p = 0;
- double area = 0;
- double t;
+ long area = 0;
avl_tree albero = NULL;
-
AVL_table *array;
generic_cell uc;
@@ -566,9 +539,6 @@
masked = TRUE;
}
- Rast_set_f_null_value(&precCell, 1);
-
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -578,73 +548,71 @@
}
buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_f_null_value(&precCell, 1);
-
- for (i = 0; i < ad->cl; i++) { /* for each fcell in the row */
-
- area++;
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, uc.t))) {
- a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
- if (corrCell != precCell) {
+ area++;
+ }
+
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
+ if (albero == NULL) {
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
- uc.val.fc = precCell;
- albero = avl_make(uc, totCorr);
- if (albero == NULL) {
- G_fatal_error("avl_make error");
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+
+ m++;
+ }
+ else {
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
return RLI_ERRORE;
}
- m++;
- }
- else {
- uc.val.fc = precCell;
- ris = avl_add(&albero, uc, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avl_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- m++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avl_make unknown error");
- return RLI_ERRORE;
- }
+ case AVL_ADD:
+ {
+ m++;
+ break;
}
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_make unknown error");
+ return RLI_ERRORE;
+ }
}
- totCorr = 1;
- } /* endif not equal fcells */
- else { /*equal fcells */
-
- totCorr++;
}
- precCell = corrCell;
- }
-
-
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.fc = precCell;
albero = avl_make(uc, totCorr);
@@ -681,47 +649,44 @@
}
}
- array = G_malloc(m * sizeof(AVL_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avl_to_array(albero, zero, array);
+ if (area > 0) {
+ double alpha;
+ double pi;
+ double t;
+ double sum;
- if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
+ alpha = atof(par[0]);
- char *sval;
+ array = G_malloc(m * sizeof(AVL_tableRow));
+ if (array == NULL) {
+ G_fatal_error("malloc array failed");
+ return RLI_ERRORE;
+ }
+ tot = avl_to_array(albero, zero, array);
+ if (tot != m) {
+ G_warning("avl_to_array unexpected value. the result could be wrong");
+ return RLI_ERRORE;
+ }
- sval = par[0];
- double alpha_double;
-
- alpha_double = (double)atof(sval);
- /* calculate index summary */
- for (i = 0; i < m; i++) {
- t = (double)(array[i]->tot);
- p = t / area;
- G_debug(1, "Valore p: %g, valore pow: %g", p, pow(p, alpha_double));
- somma = somma + pow(p, alpha_double);
+ /* calculate renyi index */
+ sum = 0;
+ for (i = 0; i < m; i++) {
+ t = array[i]->tot;
+ pi = t / area;
+ sum += pow(pi, alpha);
+ }
+ G_free(array);
+
+ *result = (1 / (1 - alpha)) * log(sum);
}
+ else
+ Rast_set_d_null_value(result, 1);
- indice = (1 / (1 - alpha_double)) * log(somma);
-
- if (isnan(indice) || isinf(indice)) {
- indice = -1;
+ avl_destroy(albero);
+ if (masked) {
+ close(mask_fd);
+ G_free(mask_buf);
}
- G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
-
- *result = indice;
-
-
- G_free(array);
- if (masked)
- G_free(mask_buf);
-
return RLI_OK;
-
}
Modified: grass/trunk/raster/r.li/r.li.richness/richness.c
===================================================================
--- grass/trunk/raster/r.li/r.li.richness/richness.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.richness/richness.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,6 +1,6 @@
/*
- * \brief calculates dominance's diversity index
+ * \brief calculates richness diversity index
*
* \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
* Commission from Faunalia Pontedera (PI) www.faunalia.it
@@ -109,7 +109,7 @@
CELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
int a = 0; /* a=0 if all cells are null */
@@ -137,9 +137,6 @@
masked = TRUE;
}
- Rast_set_c_null_value(&precCell, 1);
-
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -149,6 +146,7 @@
}
buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+ Rast_set_c_null_value(&precCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
@@ -158,9 +156,6 @@
if (!(Rast_is_null_value(&corrCell, uc.t))) {
a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
if (corrCell != precCell) {
if (albero == NULL) {
uc.val.c = precCell;
@@ -202,14 +197,13 @@
;
}
- precCell = corrCell;
}
-
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (!(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.c = precCell;
albero = avl_make(uc, (long)1);
@@ -268,7 +262,7 @@
DCELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
int a = 0; /* a=0 if all cells are null */
@@ -295,8 +289,6 @@
masked = TRUE;
}
- Rast_set_d_null_value(&precCell, 1);
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -306,6 +298,7 @@
}
buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_d_null_value(&precCell, 1);
for (i = 0; i < ad->cl; i++) { /* for each dcell in the row */
corrCell = buf[i + ad->x];
@@ -317,9 +310,6 @@
if (!(Rast_is_null_value(&corrCell, uc.t))) {
a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
if (corrCell != precCell) {
if (albero == NULL) {
uc.val.dc = precCell;
@@ -361,15 +351,13 @@
;
}
- precCell = corrCell;
}
-
-
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (!(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.dc = precCell;
albero = avl_make(uc, (long)1);
@@ -430,7 +418,7 @@
FCELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
int a = 0; /* a=0 if all cells are null */
@@ -457,9 +445,6 @@
masked = TRUE;
}
- Rast_set_f_null_value(&precCell, 1);
-
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -469,8 +454,8 @@
}
buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_f_null_value(&precCell, 1);
-
for (i = 0; i < ad->cl; i++) { /* for each fcell in the row */
corrCell = buf[i + ad->x];
@@ -481,9 +466,7 @@
if (!(Rast_is_null_value(&corrCell, uc.t))) {
a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
+
if (corrCell != precCell) {
if (albero == NULL) {
uc.val.fc = precCell;
@@ -525,15 +508,13 @@
;
}
- precCell = corrCell;
}
-
-
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (!(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.fc = precCell;
albero = avl_make(uc, (long)1);
Modified: grass/trunk/raster/r.li/r.li.shannon/shannon.c
===================================================================
--- grass/trunk/raster/r.li/r.li.shannon/shannon.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.shannon/shannon.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,19 @@
-/*
- * \brief calculates shannon's diversity index
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.shannon
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Rewrite: Markus Metz
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- *
- */
+ * PURPOSE: calculates Shannon's diversity index
+ * COPYRIGHT: (C) 2007-2014 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/raster.h>
@@ -17,11 +23,12 @@
#include <fcntl.h>
#include <math.h>
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
#include "../r.li.daemon/avlDefs.h"
#include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
+/* template for dominance, renyi, pielou, simpson */
+
int calculate(int fd, struct area_entry *ad, double *result);
int calculateD(int fd, struct area_entry *ad, double *result);
int calculateF(int fd, struct area_entry *ad, double *result);
@@ -55,19 +62,14 @@
return calculateIndex(conf->answer, shannon, NULL, raster->answer,
output->answer);
-
}
int shannon(int fd, char **par, struct area_entry * ad, double *result)
{
-
int ris = RLI_OK;
double indice = 0;
- struct Cell_head hd;
- Rast_get_cellhd(ad->raster, "", &hd);
-
switch (ad->data_type) {
case CELL_TYPE:
{
@@ -98,7 +100,6 @@
*result = indice;
return RLI_OK;
-
}
@@ -106,42 +107,31 @@
{
CELL *buf;
CELL corrCell;
+ CELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- generic_cell cc;
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = CELL_TYPE;
+ uc.t = CELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
return RLI_ERRORE;
- mask_buf = G_malloc(Rast_window_cols() * sizeof(int));
+ mask_buf = G_malloc(ad->cl * sizeof(int));
if (mask_buf == NULL) {
G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
@@ -149,10 +139,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -160,31 +147,42 @@
}
}
+ buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+ Rast_set_c_null_value(&precCell, 1);
+
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.c = corrCell;
- albero = avl_make(cc, 1);
-
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.c = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -202,53 +200,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
- }
- } /* end for */
- } /* end for */
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
/*last closing */
- if (a != 0 && albero != NULL) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+ m++;
+ }
+ else {
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
+ }
- array = G_malloc(m * sizeof(AVL_tableRow *));
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
+ array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
G_free(array);
- indice = (-1) * somma;
+ *result = -shannon;
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
@@ -258,37 +294,26 @@
{
DCELL *buf;
DCELL corrCell;
+ DCELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- generic_cell cc;
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = DCELL_TYPE;
+ uc.t = DCELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -301,10 +326,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -312,30 +334,42 @@
}
}
- for (i = 0; i < ad->cl; i++) { /* for each dcell in the row */
- area++;
+ buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_d_null_value(&precCell, 1);
+
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.dc = corrCell;
- albero = avl_make(cc, 1);
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.dc = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -353,53 +387,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
+
+ /*last closing */
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
}
- } /*close for */
- } /*close for */
+ m++;
+ }
+ else {
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
+ }
- /*last closing */
- if (a != 0 && albero != NULL) {
- array = G_malloc(m * sizeof(AVL_tableRow *));
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
+ array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning
- ("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
G_free(array);
- indice = (-1) * somma;
+ *result = -shannon;
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
@@ -409,37 +481,26 @@
{
FCELL *buf;
FCELL corrCell;
+ FCELL precCell;
int i, j;
int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
+ long totCorr = 1;
- double indice = 0;
- double somma = 0;
- double percentuale = 0;
- double area = 0;
- double t;
- double logaritmo;
+ long area = 0;
- generic_cell cc;
avl_tree albero = NULL;
AVL_table *array;
+ generic_cell uc;
- cc.t = FCELL_TYPE;
+ uc.t = FCELL_TYPE;
- if (ad->y + ad->rl > Rast_window_rows())
- G_fatal_error("Region dimensions are wrong: n rows %d > %d",
- ad->y + ad->rl, Rast_window_rows());
- if (ad->x + ad->cl > Rast_window_cols())
- G_fatal_error("Region dimensions are wrong; n cols %d > %d",
- ad->x + ad->cl, Rast_window_cols());
-
/* open mask if needed */
if (ad->mask == 1) {
if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -452,10 +513,7 @@
masked = TRUE;
}
- /*for each row */
- for (j = 0; j < ad->rl; j++) {
- buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
-
+ for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
G_fatal_error("mask read failed");
@@ -463,29 +521,42 @@
}
}
- for (i = 0; i < ad->cl; i++) { /* for each fcell in the row */
- area++;
+ buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_f_null_value(&precCell, 1);
+
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
- if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
- a = 1;
+ if (!(Rast_is_null_value(&corrCell, uc.t))) {
+ area++;
+ }
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
if (albero == NULL) {
- cc.val.fc = corrCell;
- albero = avl_make(cc, 1);
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
G_fatal_error("avl_make error");
return RLI_ERRORE;
}
+
m++;
}
else {
- cc.val.fc = corrCell;
- ris = avl_add(&albero, cc, 1);
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
switch (ris) {
case AVL_ERR:
{
@@ -503,52 +574,91 @@
}
default:
{
- G_fatal_error("avl_add unknown error");
+ G_fatal_error("avl_make unknown error");
return RLI_ERRORE;
}
}
}
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
+ }
+ }
+
+ /*last closing */
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+ if (albero == NULL) {
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
+ if (albero == NULL) {
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
}
+ m++;
}
+ else {
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
+ return RLI_ERRORE;
+ }
+ case AVL_ADD:
+ {
+ m++;
+ break;
+ }
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_add unknown error");
+ return RLI_ERRORE;
+ }
+ }
+ }
}
- /*last closing */
- if (a != 0 && albero != NULL) {
+ if (area > 0) {
+ double t;
+ double shannon;
+ double perc, logarithm;;
+
array = G_malloc(m * sizeof(AVL_tableRow));
if (array == NULL) {
G_fatal_error("malloc array failed");
return RLI_ERRORE;
}
tot = avl_to_array(albero, zero, array);
-
if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
+ G_warning("avl_to_array unexpected value. the result could be wrong");
return RLI_ERRORE;
}
- /* calculate summary */
+ /* calculate shannon */
+ shannon = 0;
for (i = 0; i < m; i++) {
- t = (double)array[i]->tot;
- percentuale = (double)(t / area);
- logaritmo = (double)log(percentuale);
- somma = somma + (percentuale * logaritmo);
+ t = array[i]->tot;
+ perc = t / area;
+ logarithm = log(perc);
+ shannon += perc * logarithm;
}
-
G_free(array);
- indice = (-1) * somma;
+ *result = -shannon;
}
else
- /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- *result = indice;
-
+ avl_destroy(albero);
if (masked) {
close(mask_fd);
G_free(mask_buf);
}
- avl_destroy(albero);
return RLI_OK;
}
Modified: grass/trunk/raster/r.li/r.li.shape/main.c
===================================================================
--- grass/trunk/raster/r.li/r.li.shape/main.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.shape/main.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -53,20 +53,17 @@
return calculateIndex(conf->answer, shape_index, NULL, raster->answer,
output->answer);
-
}
int shape_index(int fd, char **par, struct area_entry *ad, double *result)
{
-
-
double area;
struct Cell_head hd;
CELL complete_value;
double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
int mask_fd = -1, null_count = 0;
int i = 0, k = 0;
- int *mask_buf;
+ int *mask_buf = NULL;
Rast_set_c_null_value(&complete_value, 1);
Rast_get_cellhd(ad->raster, "", &hd);
@@ -108,5 +105,6 @@
(ad->rl * ad->cl - null_count);
*result = area;
+
return 1;
}
Modified: grass/trunk/raster/r.li/r.li.simpson/simpson.c
===================================================================
--- grass/trunk/raster/r.li/r.li.simpson/simpson.c 2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.simpson/simpson.c 2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,32 +1,38 @@
-
-/*
- * \brief calculates Simpson's diversity index
+/****************************************************************************
*
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE: r.li.simpson
+ * AUTHOR(S): Serena Pallecchi (original contributor)
+ * student of Computer Science University of Pisa (Italy)
+ * Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * Rewrite: Markus Metz
*
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- *
- */
+ * PURPOSE: calculates Simpson's diversity index
+ * COPYRIGHT: (C) 2007-2014 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/raster.h>
-#include <grass/glocale.h>
-
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
-#include "../r.li.daemon/defs.h"
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
+#include "../r.li.daemon/daemon.h"
#include "../r.li.daemon/avlDefs.h"
#include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
-double calculate(struct area_entry *ad, int fd, double *result);
-double calculateD(struct area_entry *ad, int fd, double *result);
-double calculateF(struct area_entry *ad, int fd, double *result);
+/* template is shannon */
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
int main(int argc, char *argv[])
{
struct Option *raster, *conf, *output;
@@ -56,31 +62,27 @@
return calculateIndex(conf->answer, simpson, NULL, raster->answer,
output->answer);
-
}
int simpson(int fd, char **par, struct area_entry *ad, double *result)
{
int ris = RLI_OK;
double indice = 0;
- struct Cell_head hd;
- Rast_get_cellhd(ad->raster, "", &hd);
-
switch (ad->data_type) {
case CELL_TYPE:
{
- ris = calculate(ad, fd, &indice);
+ ris = calculate(fd, ad, &indice);
break;
}
case DCELL_TYPE:
{
- ris = calculateD(ad, fd, &indice);
+ ris = calculateD(fd, ad, &indice);
break;
}
case FCELL_TYPE:
{
- ris = calculateF(ad, fd, &indice);
+ ris = calculateF(fd, ad, &indice);
break;
}
default:
@@ -88,7 +90,6 @@
G_fatal_error("data type unknown");
return RLI_ERRORE;
}
-
}
if (ris != RLI_OK)
@@ -97,41 +98,34 @@
*result = indice;
return RLI_OK;
-
}
-
-double calculate(struct area_entry *ad, int fd, double *result)
+int calculate(int fd, struct area_entry *ad, double *result)
{
CELL *buf;
CELL corrCell;
CELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
- long totCorr = 0;
+ long totCorr = 1;
- double indice = 0;
double somma = 0;
double p = 0;
- double area = 0;
+ long area = 0;
double t;
avl_tree albero = NULL;
-
AVL_table *array;
-
generic_cell uc;
-
uc.t = CELL_TYPE;
/* open mask if needed */
@@ -146,9 +140,6 @@
masked = TRUE;
}
- Rast_set_c_null_value(&precCell, 1);
-
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -158,70 +149,71 @@
}
buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+ Rast_set_c_null_value(&precCell, 1);
+
for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
- area++;
corrCell = buf[i + ad->x];
if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_c_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, uc.t))) {
- a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
- if (corrCell != precCell) {
+ area++;
+ }
+
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
+ if (albero == NULL) {
+ uc.val.c = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
- uc.val.c = precCell;
- albero = avl_make(uc, totCorr);
- if (albero == NULL) {
- G_fatal_error("avl_make error");
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+
+ m++;
+ }
+ else {
+ uc.val.c = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
return RLI_ERRORE;
}
- else
+ case AVL_ADD:
+ {
m++;
- }
- else {
- uc.val.c = precCell;
- ris = avl_add(&albero, uc, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avl_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- m++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avl_make unknown error");
- return RLI_ERRORE;
- }
+ break;
}
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_make unknown error");
+ return RLI_ERRORE;
+ }
}
- totCorr = 1;
- } /* endif not equal cells */
- else { /*equal cells */
-
- totCorr++;
}
- precCell = corrCell;
- }
-
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.c = precCell;
albero = avl_make(uc, totCorr);
@@ -257,68 +249,65 @@
}
}
}
- array = G_malloc(m * sizeof(AVL_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avl_to_array(albero, zero, array);
- if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- /* claculate index summary */
- for (i = 0; i < m; i++) {
- t = (double)(array[i]->tot);
- p = t / area;
- somma = somma + (p * p);
- }
+ if (area > 0) {
+ array = G_malloc(m * sizeof(AVL_tableRow));
+ if (array == NULL) {
+ G_fatal_error("malloc array failed");
+ return RLI_ERRORE;
+ }
+ tot = avl_to_array(albero, zero, array);
+ if (tot != m) {
+ G_warning("avl_to_array unexpected value. the result could be wrong");
+ return RLI_ERRORE;
+ }
- if (a != 0) {
- indice = 1 - somma;
+ /* calculate index summary */
+ for (i = 0; i < m; i++) {
+ t = (double)(array[i]->tot);
+ p = t / area;
+ somma = somma + (p * p);
+ }
+ G_free(array);
+
+ *result = 1 - somma;
}
- else /*if a is 0, that is all cell are null, i put index=-1 */
- indice = (double)(-1);
+ else
+ Rast_set_d_null_value(result, 1);
-
- G_free(array);
- if (masked)
+ avl_destroy(albero);
+ if (masked) {
+ close(mask_fd);
G_free(mask_buf);
+ }
- *result = indice;
-
return RLI_OK;
}
-double calculateD(struct area_entry *ad, int fd, double *result)
+int calculateD(int fd, struct area_entry *ad, double *result)
{
DCELL *buf;
DCELL corrCell;
DCELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
- long totCorr = 0;
+ long totCorr = 1;
- double indice = 0;
double somma = 0;
double p = 0;
- double area = 0;
+ long area = 0;
double t;
avl_tree albero = NULL;
-
AVL_table *array;
-
generic_cell uc;
uc.t = DCELL_TYPE;
@@ -329,14 +318,12 @@
return RLI_ERRORE;
mask_buf = G_malloc(ad->cl * sizeof(int));
if (mask_buf == NULL) {
- G_fatal_error("malloc mask_buffailed");
+ G_fatal_error("malloc mask_buf failed");
return RLI_ERRORE;
}
masked = TRUE;
}
- Rast_set_d_null_value(&precCell, 1);
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -346,72 +333,71 @@
}
buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_d_null_value(&precCell, 1);
- for (i = 0; i < ad->cl; i++) { /* for each dcell in the row */
- area++;
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_d_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, uc.t))) {
- a = 1;
+ area++;
+ }
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
- if (corrCell != precCell) {
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
+ if (albero == NULL) {
+ uc.val.dc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
- uc.val.dc = precCell;
- albero = avl_make(uc, totCorr);
- if (albero == NULL) {
- G_fatal_error("avl_make error");
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+
+ m++;
+ }
+ else {
+ uc.val.dc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
return RLI_ERRORE;
}
- m++;
- }
- else {
- uc.val.dc = precCell;
- ris = avl_add(&albero, uc, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avl_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- m++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avl_make unknown error");
- return RLI_ERRORE;
- }
+ case AVL_ADD:
+ {
+ m++;
+ break;
}
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_make unknown error");
+ return RLI_ERRORE;
+ }
}
- totCorr = 1;
- } /* endif not equal dcells */
- else { /*equal dcells */
-
- totCorr++;
}
- precCell = corrCell;
- }
-
-
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.dc = precCell;
albero = avl_make(uc, totCorr);
@@ -447,67 +433,65 @@
}
}
}
- array = G_malloc(m * sizeof(AVL_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avl_to_array(albero, zero, array);
- if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
- /* claculate index summary */
- for (i = 0; i < m; i++) {
- t = (double)(array[i]->tot);
- p = t / area;
- somma = somma + (p * p);
- }
+ if (area > 0) {
+ array = G_malloc(m * sizeof(AVL_tableRow));
+ if (array == NULL) {
+ G_fatal_error("malloc array failed");
+ return RLI_ERRORE;
+ }
+ tot = avl_to_array(albero, zero, array);
+ if (tot != m) {
+ G_warning("avl_to_array unexpected value. the result could be wrong");
+ return RLI_ERRORE;
+ }
- if (a != 0) { /*if a is 0, that is all cell are null, i put index=-1 */
- indice = 1 - somma;
+ /* calculate index summary */
+ for (i = 0; i < m; i++) {
+ t = (double)(array[i]->tot);
+ p = t / area;
+ somma = somma + (p * p);
+ }
+ G_free(array);
+
+ *result = 1 - somma;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
- G_free(array);
- if (masked)
+ avl_destroy(albero);
+ if (masked) {
+ close(mask_fd);
G_free(mask_buf);
+ }
- *result = indice;
return RLI_OK;
}
-
-double calculateF(struct area_entry *ad, int fd, double *result)
+int calculateF(int fd, struct area_entry *ad, double *result)
{
FCELL *buf;
FCELL corrCell;
FCELL precCell;
int i, j;
- int mask_fd = -1, *mask_buf;
+ int mask_fd = -1, *mask_buf = NULL;
int ris = 0;
int masked = FALSE;
- int a = 0; /* a=0 if all cells are null */
long m = 0;
long tot = 0;
long zero = 0;
- long totCorr = 0;
+ long totCorr = 1;
- double indice = 0;
double somma = 0;
double p = 0;
- double area = 0;
+ long area = 0;
double t;
avl_tree albero = NULL;
-
AVL_table *array;
-
generic_cell uc;
uc.t = FCELL_TYPE;
@@ -524,9 +508,6 @@
masked = TRUE;
}
- Rast_set_f_null_value(&precCell, 1);
-
-
for (j = 0; j < ad->rl; j++) { /* for each row */
if (masked) {
if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -536,73 +517,71 @@
}
buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+ Rast_set_f_null_value(&precCell, 1);
-
- for (i = 0; i < ad->cl; i++) { /* for each fcell in the row */
-
- area++;
+ for (i = 0; i < ad->cl; i++) { /* for each cell in the row */
corrCell = buf[i + ad->x];
- if (masked && mask_buf[i + ad->x] == 0) {
+ if ((masked) && (mask_buf[i + ad->x] == 0)) {
Rast_set_f_null_value(&corrCell, 1);
- area--;
}
if (!(Rast_is_null_value(&corrCell, uc.t))) {
- a = 1;
- if (Rast_is_null_value(&precCell, uc.t)) {
- precCell = corrCell;
- }
- if (corrCell != precCell) {
+ area++;
+ }
+
+ if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell == precCell) {
+
+ totCorr++;
+ }
+ else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+ corrCell != precCell) {
+
+ /* add precCell to search tree */
+ if (albero == NULL) {
+ uc.val.fc = precCell;
+ albero = avl_make(uc, totCorr);
if (albero == NULL) {
- uc.val.fc = precCell;
- albero = avl_make(uc, totCorr);
- if (albero == NULL) {
- G_fatal_error("avl_make error");
+ G_fatal_error("avl_make error");
+ return RLI_ERRORE;
+ }
+
+ m++;
+ }
+ else {
+ uc.val.fc = precCell;
+ ris = avl_add(&albero, uc, totCorr);
+ switch (ris) {
+ case AVL_ERR:
+ {
+ G_fatal_error("avl_add error");
return RLI_ERRORE;
}
- m++;
- }
- else {
- uc.val.fc = precCell;
- ris = avl_add(&albero, uc, totCorr);
- switch (ris) {
- case AVL_ERR:
- {
- G_fatal_error("avl_add error");
- return RLI_ERRORE;
- }
- case AVL_ADD:
- {
- m++;
- break;
- }
- case AVL_PRES:
- {
- break;
- }
- default:
- {
- G_fatal_error("avl_make unknown error");
- return RLI_ERRORE;
- }
+ case AVL_ADD:
+ {
+ m++;
+ break;
}
+ case AVL_PRES:
+ {
+ break;
+ }
+ default:
+ {
+ G_fatal_error("avl_make unknown error");
+ return RLI_ERRORE;
+ }
}
- totCorr = 1;
- } /* endif not equal fcells */
- else { /*equal fcells */
-
- totCorr++;
}
- precCell = corrCell;
- }
-
-
+ totCorr = 1;
+ } /* endif not equal cells */
+ precCell = corrCell;
}
}
/*last closing */
- if (a != 0) {
+ if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
if (albero == NULL) {
uc.val.fc = precCell;
albero = avl_make(uc, totCorr);
@@ -639,36 +618,36 @@
}
}
- array = G_malloc(m * sizeof(AVL_tableRow));
- if (array == NULL) {
- G_fatal_error("malloc array failed");
- return RLI_ERRORE;
- }
- tot = avl_to_array(albero, zero, array);
- if (tot != m) {
- G_warning("avl_to_array unaspected value. the result could be wrong");
- return RLI_ERRORE;
- }
+ if (area > 0) {
+ array = G_malloc(m * sizeof(AVL_tableRow));
+ if (array == NULL) {
+ G_fatal_error("malloc array failed");
+ return RLI_ERRORE;
+ }
+ tot = avl_to_array(albero, zero, array);
+ if (tot != m) {
+ G_warning("avl_to_array unexpected value. the result could be wrong");
+ return RLI_ERRORE;
+ }
- /* calculate index summary */
- for (i = 0; i < m; i++) {
- t = (double)(array[i]->tot);
- p = t / area;
- somma = somma + (p * p);
- }
+ /* calculate index summary */
+ for (i = 0; i < m; i++) {
+ t = (double)(array[i]->tot);
+ p = t / area;
+ somma = somma + (p * p);
+ }
+ G_free(array);
- if (a != 0) { /*if a is 0, that is all cell are null, i put index=-1 */
- indice = 1 - somma;
+ *result = 1 - somma;
}
else
- indice = (double)(-1);
+ Rast_set_d_null_value(result, 1);
-
- G_free(array);
- if (masked)
+ avl_destroy(albero);
+ if (masked) {
+ close(mask_fd);
G_free(mask_buf);
+ }
-
- *result = indice;
return RLI_OK;
}
More information about the grass-commit
mailing list