[GRASS-SVN] r60563 - grass/trunk/raster/r.distance

svn_grass at osgeo.org svn_grass at osgeo.org
Wed May 28 14:09:09 PDT 2014


Author: hcho
Date: 2014-05-28 14:09:09 -0700 (Wed, 28 May 2014)
New Revision: 60563

Modified:
   grass/trunk/raster/r.distance/defs.h
   grass/trunk/raster/r.distance/main.c
   grass/trunk/raster/r.distance/parse.c
   grass/trunk/raster/r.distance/report.c
Log:
r.distance: -s/-r sort by distance implemented

Modified: grass/trunk/raster/r.distance/defs.h
===================================================================
--- grass/trunk/raster/r.distance/defs.h	2014-05-28 21:00:04 UTC (rev 60562)
+++ grass/trunk/raster/r.distance/defs.h	2014-05-28 21:09:09 UTC (rev 60563)
@@ -52,6 +52,9 @@
     char *fs;			/* report field separator     */
     int overlap;		/* checking for overlapping, than distance is 0 */
     int null;			/* report null objects as * */
+    int sort;			/* 0: sort by cat1,cat2 (default)
+				   1: sort by distance in ascending order
+				   2: sort by distance in descending order */
 };
 
 /* distance.c */

Modified: grass/trunk/raster/r.distance/main.c
===================================================================
--- grass/trunk/raster/r.distance/main.c	2014-05-28 21:00:04 UTC (rev 60562)
+++ grass/trunk/raster/r.distance/main.c	2014-05-28 21:09:09 UTC (rev 60563)
@@ -4,11 +4,12 @@
  * MODULE:       r.distance
  *
  * AUTHOR(S):    Michael Shapiro - CERL
+ *               Sort/reverse sort by distance by Huidae Cho
  *
  * PURPOSE:      Locates the closest points between objects in two 
  *               raster maps.
  *
- * COPYRIGHT:    (C) 2003, 2012 by the GRASS Development Team
+ * COPYRIGHT:    (C) 2003-2014 by the GRASS Development Team
  *
  *               This program is free software under the GNU General
  *               Public License (>=v2). Read the file COPYING that

Modified: grass/trunk/raster/r.distance/parse.c
===================================================================
--- grass/trunk/raster/r.distance/parse.c	2014-05-28 21:00:04 UTC (rev 60562)
+++ grass/trunk/raster/r.distance/parse.c	2014-05-28 21:09:09 UTC (rev 60563)
@@ -25,7 +25,7 @@
 void parse(int argc, char *argv[], struct Parms *parms)
 {
     struct Option *maps, *fs;
-    struct Flag *labels, *overlap, *null;
+    struct Flag *labels, *overlap, *null, *sort, *revsort;
     const char *name, *mapset;
 
     maps = G_define_standard_option(G_OPT_R_MAPS);
@@ -48,9 +48,21 @@
     null->key = 'n';
     null->description = _("Report null objects as *");
 
+    sort = G_define_flag();
+    sort->key = 's';
+    sort->description = _("Sort by distance in ascending order");
+
+    revsort = G_define_flag();
+    revsort->key = 'r';
+    revsort->description = _("Sort by distance in descending order");
+
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
+    if (sort->answer && revsort->answer)
+	G_fatal_error(_("-%c and -%c are mutually exclusive"),
+		      sort->key, revsort->key);
+
     name = parms->map1.name = maps->answers[0];
     mapset = parms->map1.mapset = G_find_raster2(name, "");
     if (mapset == NULL)
@@ -73,4 +85,5 @@
     parms->fs = fs->answer;
     parms->overlap = overlap->answer ? 1 : 0;
     parms->null = null->answer ? 1 : 0;
+    parms->sort = sort->answer ? 1 : (revsort->answer ? 2 : 0);
 }

Modified: grass/trunk/raster/r.distance/report.c
===================================================================
--- grass/trunk/raster/r.distance/report.c	2014-05-28 21:00:04 UTC (rev 60562)
+++ grass/trunk/raster/r.distance/report.c	2014-05-28 21:09:09 UTC (rev 60563)
@@ -16,19 +16,37 @@
  *
  ***************************************************************************/
 
+#include <stdlib.h>
 #include <grass/glocale.h>
 
 #include "defs.h"
 
+struct ReportLine
+{
+    CELL cat1;
+    CELL cat2;
+    int isnull1;
+    int isnull2;
+    double east1;
+    double north1;
+    double east2;
+    double north2;
+    double distance;
+};
+
+static void print(struct ReportLine *, struct Parms *);
+static int compare(const void *, const void *);
+static int revcompare(const void *, const void *);
+
 void report(struct Parms *parms)
 {
     int i1, i2;
     struct Map *map1, *map2;
-    char *fs;
     double distance, north1, east1, north2, east2;
     struct Cell_head region;
     struct CatEdgeList *list1, *list2;
-    char temp[100];
+    struct ReportLine *lines;
+    int nlines;
 
     extern void find_minimum_distance();
     extern char *get_label();
@@ -38,10 +56,17 @@
 
     map1 = &parms->map1;
     map2 = &parms->map2;
-    fs = parms->fs;
 
     G_message(_("Processing..."));
 
+    if (parms->sort > 0)
+	lines = (struct ReportLine *)G_malloc(
+			map1->edges.ncats * map2->edges.ncats *
+			sizeof(struct ReportLine));
+    else
+	lines = NULL;
+    nlines = 0;
+
     for (i1 = 0; i1 < map1->edges.ncats; i1++) {
 	int isnull1;
 
@@ -50,6 +75,7 @@
 
 	for (i2 = 0; i2 < map2->edges.ncats; i2++) {
 	    int isnull2;
+	    struct ReportLine line;
 
 	    list2 = &map2->edges.catlist[i2];
 	    isnull2 = parms->null ? Rast_is_c_null_value(&(list2->cat)) : 0;
@@ -59,42 +85,113 @@
 				  &region, parms->overlap, map1->name,
 				  map2->name);
 
-	    /* print cat numbers */
-	    if (isnull1 && isnull2)
-	        fprintf(stdout, "*%s*", fs);
-	    else if (isnull1)
-	        fprintf(stdout, "*%s%ld", fs, (long)list2->cat);
-	    else if (isnull2)
-	        fprintf(stdout, "%ld%s*", (long)list1->cat, fs);
+	    line.cat1 = list1->cat;
+	    line.cat2 = list2->cat;
+	    line.isnull1 = isnull1;
+	    line.isnull2 = isnull2;
+	    line.east1 = east1;
+	    line.north1 = north1;
+	    line.east2 = east2;
+	    line.north2 = north2;
+	    line.distance = distance;
+
+	    if (parms->sort > 0)
+		lines[nlines++] = line;
 	    else
-	        fprintf(stdout, "%ld%s%ld", (long)list1->cat, fs,
-		        (long)list2->cat);
+		print(&line, parms);
+	}
+    }
 
-	    /* print distance */
-	    sprintf(temp, "%.10f", distance);
-	    G_trim_decimal(temp);
-	    fprintf(stdout, "%s%s", fs, temp);
+    if (parms->sort > 0) {
+	int i;
 
-	    /* print coordinates of the closest pair */
-	    G_format_easting(east1, temp,
-			     G_projection() == PROJECTION_LL ? -1 : 0);
-	    fprintf(stdout, "%s%s", fs, temp);
-	    G_format_northing(north1, temp,
-			      G_projection() == PROJECTION_LL ? -1 : 0);
-	    fprintf(stdout, "%s%s", fs, temp);
-	    G_format_easting(east2, temp,
-			     G_projection() == PROJECTION_LL ? -1 : 0);
-	    fprintf(stdout, "%s%s", fs, temp);
-	    G_format_northing(north2, temp,
-			      G_projection() == PROJECTION_LL ? -1 : 0);
-	    fprintf(stdout, "%s%s", fs, temp);
+	if (parms->sort == 1)
+	    qsort(lines, nlines, sizeof(struct ReportLine), compare);
+	else
+	    qsort(lines, nlines, sizeof(struct ReportLine), revcompare);
 
-	    /* print category labels */
-	    if (parms->labels) {
-		fprintf(stdout, "%s%s", fs, get_label(map1, list1->cat));
-		fprintf(stdout, "%s%s", fs, get_label(map2, list2->cat));
-	    }
-	    fprintf(stdout, "\n");
-	}
+	for(i = 0; i < nlines; i++)
+	    print(&lines[i], parms);
     }
 }
+
+static void print(struct ReportLine *line, struct Parms *parms)
+{
+    char *fs;
+    char temp[100];
+
+    fs = parms->fs;
+
+    /* print cat numbers */
+    if (line->isnull1 && line->isnull2)
+	fprintf(stdout, "*%s*", fs);
+    else if (line->isnull1)
+	fprintf(stdout, "*%s%ld", fs, (long)line->cat2);
+    else if (line->isnull2)
+	fprintf(stdout, "%ld%s*", (long)line->cat1, fs);
+    else
+	fprintf(stdout, "%ld%s%ld", (long)line->cat1, fs, (long)line->cat2);
+
+    /* print distance */
+    sprintf(temp, "%.10f", line->distance);
+    G_trim_decimal(temp);
+    fprintf(stdout, "%s%s", fs, temp);
+
+    /* print coordinates of the closest pair */
+    G_format_easting(line->east1, temp,
+		     G_projection() == PROJECTION_LL ? -1 : 0);
+    fprintf(stdout, "%s%s", fs, temp);
+    G_format_northing(line->north1, temp,
+		      G_projection() == PROJECTION_LL ? -1 : 0);
+    fprintf(stdout, "%s%s", fs, temp);
+    G_format_easting(line->east2, temp,
+		     G_projection() == PROJECTION_LL ? -1 : 0);
+    fprintf(stdout, "%s%s", fs, temp);
+    G_format_northing(line->north2, temp,
+		      G_projection() == PROJECTION_LL ? -1 : 0);
+    fprintf(stdout, "%s%s", fs, temp);
+
+    /* print category labels */
+    if (parms->labels) {
+	struct Map *map1, *map2;
+
+	map1 = &parms->map1;
+	map2 = &parms->map2;
+
+	fprintf(stdout, "%s%s", fs, get_label(map1, line->cat1));
+	fprintf(stdout, "%s%s", fs, get_label(map2, line->cat2));
+    }
+    fprintf(stdout, "\n");
+}
+
+static int compare(const void *p1, const void *p2)
+{
+    const struct ReportLine *line1, *line2;
+
+    line1 = (const struct ReportLine *)p1;
+    line2 = (const struct ReportLine *)p2;
+
+    if (line1->distance < line2->distance) return -1; /* short distance first */
+    if (line1->distance > line2->distance) return 1;
+
+    if (!line1->isnull1 && line2->isnull1) return -1; /* non-null first */
+    if (line1->isnull1 && !line2->isnull1) return 1;
+    if (!line1->isnull1 && !line2->isnull1) {
+	if (line1->cat1 < line2->cat1) return -1; /* small cat first */
+	if (line1->cat1 > line2->cat1) return 1;
+    }
+
+    if (!line1->isnull2 && line2->isnull2) return -1;
+    if (line1->isnull2 && !line2->isnull2) return 1;
+    if (!line1->isnull2 && !line2->isnull2) {
+	if (line1->cat2 < line2->cat2) return -1;
+	if (line1->cat2 > line2->cat2) return 1;
+    }
+
+    return 0; /* same cat1, same cat2 */
+}
+
+static int revcompare(const void *p1, const void *p2)
+{
+    return -compare(p1, p2);
+}



More information about the grass-commit mailing list