|
@@ -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 @@ void report(struct Parms *parms)
|
|
|
|
|
|
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 @@ void report(struct Parms *parms)
|
|
|
|
|
|
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 @@ void report(struct Parms *parms)
|
|
|
®ion, 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 distance */
|
|
|
- sprintf(temp, "%.10f", distance);
|
|
|
- G_trim_decimal(temp);
|
|
|
- fprintf(stdout, "%s%s", fs, temp);
|
|
|
-
|
|
|
- /* 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);
|
|
|
-
|
|
|
- /* 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");
|
|
|
+ print(&line, parms);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (parms->sort > 0) {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (parms->sort == 1)
|
|
|
+ qsort(lines, nlines, sizeof(struct ReportLine), compare);
|
|
|
+ else
|
|
|
+ qsort(lines, nlines, sizeof(struct ReportLine), revcompare);
|
|
|
+
|
|
|
+ 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);
|
|
|
}
|