[GRASS-CVS]
martinl: grass6/vector/v.distance description.html, 1.11,
1.12 main.c, 1.44, 1.45
grass at intevation.de
grass at intevation.de
Thu Dec 6 09:15:17 EST 2007
Author: martinl
Update of /grassrepository/grass6/vector/v.distance
In directory doto:/tmp/cvs-serv7728
Modified Files:
description.html main.c
Log Message:
Matrix-like output for -a flag
Index: description.html
===================================================================
RCS file: /grassrepository/grass6/vector/v.distance/description.html,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- description.html 30 Mar 2006 11:40:14 -0000 1.11
+++ description.html 6 Dec 2007 14:15:14 -0000 1.12
@@ -1,76 +1,87 @@
<H2>DESCRIPTION</H2>
-<EM>v.distance</EM>
-finds features from one vector (from=) feature to another vector (to=) nearest feature.
-Various information about relation (distance, ...) may be uploaded to attribute
-table attached to first vector map or printed to 'stdout'.
-A new vector map may be created where lines connecting nearest points on features are written.
-<P>
-
+<EM>v.distance</EM> finds the nearest element in vector map
+(<B>to</B>) for elements in vector map (<B>from</B>). Various
+information about relation (distance, category, etc.) may be uploaded
+to attribute table attached to first vector map or printed to
+'stdout'. A new vector map may be created where lines connecting
+nearest points on features are written.
<h2>EXAMPLES</H2>
-1) Find <B>nearest lines</B> in vector map <B>ln</B> for points from vector map
-<B>pnt</B> within the given threshold and write related line categories to
-column <B>linecat</B> in attribute table attached to vector map <B>pnt</B>:
-<br>
+<H3>Find nearest lines</H3>
+
+Find <EM>nearest lines</EM> in vector map <B>ln</B> for points from
+vector map <B>pnt</B> within the given threshold and write related
+line categories to column <B>linecat</B> in attribute table attached
+to vector map <B>pnt</B>:
+
<div class="code"><pre>
v.distance from=pnt to=ln upload=cat column=linecat
</pre></div>
-<p>
-2) For each point from vector map <B>pnt</B> find <B>nearest area</B> from map
-<B>ar</B> within the given threshold and write the related area categories
-to column <B>areacat</B> in attribute table attached to vector map
-<B>pnt</B>. In case a point falls into a polygon area, the distance is zero:
-<br>
+<H3>Find nearest area</H3>
+
+For each point from vector map <B>pnt</B> find <EM>nearest area</EM>
+from map <B>ar</B> within the given threshold and write the related
+area categories to column <B>areacat</B> in attribute table attached
+to vector map <B>pnt</B>. In case a point falls into a polygon area,
+the distance is zero:
+
<div class="code"><pre>
v.distance from=pnt to=ar upload=cat column=areacat
</pre></div>
-<p>
-3) Create a new vector map which contains <B>lines connecting nearest
-features</B> of maps <B>pnt</B> and map <B>ln</B>. The resulting vector map
-can be used for example to connect points to a network as needed for
-network analysis:
-<br>
+<H3>Create a new vector map</H3>
+
+Create a new vector map which contains <EM>lines connecting nearest
+features</EM> of maps <B>pnt</B> and map <B>ln</B>. The resulting
+vector map can be used for example to connect points to a network as
+needed for network analysis:
+
<div class="code"><pre>
v.distance -p from=pnt to=ln out=connections upload=dist column=dist
</pre></div>
-<p>
-4) Query information from selected point(s). v.distance takes points from
- vector as input instead of stdin. First new vector map with query points,
- has to be created, then the map can be analysed:
+<H3>Query information</H3>
+
+Query information from selected point(s). <EM>v.distance</EM> takes
+points from vector map as input instead of stdin. First new vector map
+with query points, has to be created, then the map can be analysed:
<br>
-Create query map (if not present):<br>
+
+Create query map (if not present):
+
<div class="code"><pre>
echo "123456|654321|1" | v.in.ascii output=pnt
</pre></div>
-<br>
-Find nearest features:<br>
+
+Find nearest features:
+
<div class="code"><pre>
v.distance from=pnt to=map_to_query upload=cat col=somecol -p
</pre></div>
-<p>
-5) Point-in-polygon: Find <B>area</B> from vector map <B>ar</B> for each point
-from vector map <B>pnt</B> in which the individual point falls into and write
-the related area categories to column <B>areacat</B> into attribute table
-attached to vector map <B>pnt</B>:
-<br>
+<H3>Point-in-polygon</H3>
+
+Find <EM>area</EM> from vector map <B>ar</B> for each point from
+vector map <B>pnt</B> in which the individual point falls into and
+write the related area categories to column <B>areacat</B> into
+attribute table attached to vector map <B>pnt</B>:
+
<div class="code"><pre>
v.distance from=pnt to=ar dmax=0 upload=cat column=areacat
</pre></div>
-<p>
-6) Univariate statistics on results: Create a vector map containing connecting
-lines and investigate mean distance to targets.<br>
-An alternative solution is to use the <tt>v.distance upload=dist</tt> option
-to upload distances into the <i>bugs</i> vector directly, then run v.univar
-on that. Also note you can upload two columns at a time.<BR>
-e.g. <tt>v.distance upload=cat,dist column=nearest_id,dist_to_nr</tt>
-<br>
+<H3>Univariate statistics on results</H3>
+
+Create a vector map containing connecting lines and investigate mean
+distance to targets. An alternative solution is to use
+the <tt>v.distance upload=dist</tt> option to upload distances into
+the <i>bugs</i> vector directly, then run v.univar on that. Also note
+you can upload two columns at a time, e.g. <tt>v.distance
+upload=cat,dist column=nearest_id,dist_to_nr</tt>.
+
<div class="code"><pre>
# create working copy
g.copy vect=bugsites,bugs
@@ -93,12 +104,23 @@
v.univar vdistance_vectors column=length
</pre></div>
+<H3>Print distance matrix</H3>
+
+<div class="code"><pre>
+v.distance -pa from=archsites to=archsites upload=dist col=dist
+</pre></div>
+
+Note: Matrix-like output is enabled only for flag <EM>-a</EM> and one
+given upload option.
<H2>NOTES</H2>
-If a nearest feature does not have a category, column is updated to <B>null</B>.
-This is true also for areas, which means for example, that if point is in island
-(area WITHOUT category), v.distance does not search for nearest area WITH category,
-island is identified as nearest and category updated to null.
+
+If a nearest feature does not have a category, column is updated
+to <B>null</B>. This is true also for areas, which means for example,
+that if point is in island (area WITHOUT
+category), <EM>v.distance</EM> does not search for nearest area WITH
+category, island is identified as nearest and category updated to
+null.
<p>
The upload <B>column</B>(s) must already exist. Create one with <em>v.db.addcol</em>.
@@ -113,11 +135,9 @@
<H2>AUTHOR</H2>
-Janne Soimasuo 1994, Finland<br>
-University of Joensuu, Faculty of Forestry, Finland
-<p>
-5.0 cmd line coordinates support: Markus Neteler, ITC-irst, Trento, Italy<BR>
-<p>
-5.1 update Radim Blazek, ITC-irst, Trento, Italy
+Janne Soimasuo 1994, University of Joensuu, Faculty of Forestry, Finland<BR>
+Cmd line coordinates support: Markus Neteler, ITC-irst, Trento, Italy<BR>
+Updated for 5.1: Radim Blazek, ITC-irst, Trento, Italy<BR>
+Martix-like output by Martin Landa, FBK-irst, Trento, Italy
<p><i>Last changed: $Date$</i>
Index: main.c
===================================================================
RCS file: /grassrepository/grass6/vector/v.distance/main.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- main.c 5 Dec 2007 13:56:34 -0000 1.44
+++ main.c 6 Dec 2007 14:15:14 -0000 1.45
@@ -46,29 +46,31 @@
/* Structure where are stored infos about nearest feature for each category */
typedef struct {
int from_cat; /* category (from) */
- int count; /* number of features already found */
- int to_cat; /* category (to) */
- double from_x, from_y, from_z, to_x, to_y, to_z; /* coordinates of nearest point */
- double from_along, to_along; /* distance along a linear feature to the nearest point */
- double to_angle; /* angle of linear feature in nearest point */
- double dist; /* distance to nearest feature */
+ int count; /* number of features already found */
+ int to_cat; /* category (to) */
+ double from_x, from_y, from_z, to_x, to_y, to_z; /* coordinates of nearest point */
+ double from_along, to_along; /* distance along a linear feature to the nearest point */
+ double to_angle; /* angle of linear feature in nearest point */
+ double dist; /* distance to nearest feature */
} NEAR;
/* Upload and column store */
typedef struct {
- int upload; /* code */
+ int upload; /* code */
char *column; /* column name */
} UPLOAD;
-static int cmp_near ( const void *, const void *);
-static int cmp_exist ( const void *, const void *);
-
+static int cmp_near(const void *, const void *);
+static int cmp_near_to(const void *, const void *);
+static int cmp_exist(const void *, const void *);
+static int print_upload(NEAR *, UPLOAD *, int, dbCatValArray *, dbCatVal *);
int main (int argc, char *argv[])
{
int i, j;
- int all = 0; /* calculate from each to each within the threshold */
+ int print_as_matrix; /* only for all */
+ int all; /* calculate from each to each within the threshold */
char *mapset;
struct GModule *module;
struct Option *from_opt, *to_opt, *from_type_opt, *to_type_opt, *from_field_opt, *to_field_opt;
@@ -81,7 +83,7 @@
struct line_pnts *FPoints, *TPoints;
struct line_cats *FCats, *TCats;
NEAR *Near, *near;
- int anear; /* allocated space, used only for all */
+ int anear; /* allocated space, used only for all */
UPLOAD *Upload; /* zero terminated */
int ftype, fcat, tcat, count;
int nfrom, nto, nfcats, fline, tline, tseg, tarea, area, isle, nisles;
@@ -97,6 +99,8 @@
dbCatValArray cvarr;
dbColumn *column;
+ all = 0;
+ print_as_matrix = 0;
column = NULL;
G_gisinit (argv[0]);
@@ -104,9 +108,7 @@
module = G_define_module();
module->keywords = _("vector, database, attribute table");
module->description =
- _("Finds the nearest element in vector 'to' for elements in vector 'from'. "
- "Various information about this relation may be uploaded to the "
- "attribute table of input vector 'from' or printed to stdout.");
+ _("Finds the nearest element in vector map 'to' for elements in vector map 'from'.");
from_opt = G_define_standard_option(G_OPT_V_INPUT);
from_opt->key = "from" ;
@@ -145,7 +147,8 @@
out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
out_opt->key = "output";
out_opt->required = NO;
- out_opt->description = _("Name for output vector map containing lines connecting nearest elements");
+ out_opt->description = _("Name for output vector map containing lines "
+ "connecting nearest elements");
max_opt = G_define_option();
max_opt->key = "dmax";
@@ -217,10 +220,18 @@
max = atof (max_opt->answer);
+ if ( all_flag->answer )
+ all = 1;
+
/* Read upload and column options */
/* count */
i = 0;
- while (upload_opt->answers[i]) i++;
+ while (upload_opt->answers[i])
+ i++;
+ if (strcmp(from_opt->answer, to_opt->answer) == 0 &&
+ all && !table_opt->answer && i == 1)
+ print_as_matrix = 1;
+
/* alloc */
Upload = (UPLOAD *) G_calloc ( i+1, sizeof (UPLOAD) );
/* read upload */
@@ -267,8 +278,6 @@
if ( Upload[i].upload != END )
G_fatal_error(_("Not enough column names"));
- if ( all_flag->answer ) all = 1;
-
/* Open 'from' vector */
if ((mapset = G_find_vector2 (from_opt->answer, "")) == NULL )
G_fatal_error(_("Vector map <%s> not found"), from_opt->answer);
@@ -718,7 +727,8 @@
if ( db_execute_immediate (driver, &stmt) != DB_OK )
G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&stmt));
- if (db_grant_on_table (driver, table_opt->answer, DB_PRIV_SELECT, DB_GROUP|DB_PUBLIC ) != DB_OK )
+ if (db_grant_on_table (driver, table_opt->answer, DB_PRIV_SELECT,
+ DB_GROUP|DB_PUBLIC ) != DB_OK )
G_fatal_error(_("Unable to grant privileges on table <%s>"), table_opt->answer);
} else if (!all) { /* read existing cats from table */
@@ -727,8 +737,13 @@
}
update_ok = update_err = update_exist = update_notexist = update_dupl = update_notfound = 0;
- if ( !all ) count = nfcats;
-
+ if ( !all ) {
+ count = nfcats;
+ }
+ else if (print_as_matrix) {
+ qsort( (void *)Near, count, sizeof(NEAR), cmp_near_to);
+ }
+
if ( driver )
db_begin_transaction ( driver );
@@ -773,73 +788,34 @@
}
if ( print_flag->answer || (all && !table_opt->answer) ) { /* print only */
- fprintf(stdout, "%d", Near[i].from_cat );
- j = 0;
- while ( Upload[j].upload != END ) {
- if ( Near[i].count == 0 ) { /* no nearest found */
- fprintf(stdout, "|null" );
- } else {
- switch ( Upload[j].upload ) {
- case CAT:
- if ( Near[i].to_cat >= 0 )
- fprintf(stdout, "|%d", Near[i].to_cat );
- else
- fprintf(stdout, "|null" );
-
- break;
- case DIST:
- fprintf(stdout, "|%f", Near[i].dist );
- break;
- case FROM_X:
- fprintf(stdout, "|%f", Near[i].from_x );
- break;
- case FROM_Y:
- fprintf(stdout, "|%f", Near[i].from_y );
- break;
- case TO_X:
- fprintf(stdout, "|%f", Near[i].to_x );
- break;
- case TO_Y:
- fprintf(stdout, "|%f", Near[i].to_y );
- break;
- case FROM_ALONG:
- fprintf(stdout, "|%f", Near[i].from_along );
- break;
- case TO_ALONG:
- fprintf(stdout, "|%f", Near[i].to_along );
- break;
- case TO_ANGLE:
- fprintf(stdout, "|%f", Near[i].to_angle );
- break;
- case TO_ATTR:
- if ( catval ) {
- switch (cvarr.ctype) {
- case DB_C_TYPE_INT:
- fprintf(stdout, "|%d", catval->val.i );
- break;
-
- case DB_C_TYPE_DOUBLE:
- fprintf(stdout, "|%.15e", catval->val.d );
- break;
-
- case DB_C_TYPE_STRING:
- fprintf(stdout, "|%s", db_get_string(catval->val.s) );
- break;
-
- case DB_C_TYPE_DATETIME:
- /* TODO: formating datetime */
- fprintf(stdout, "|" );
- break;
- }
- } else {
- fprintf(stdout, "|null" );
- }
- break;
+ /*
+ input and output is the same &&
+ calculate distances &&
+ only one upload option given ->
+ print as a matrix
+ */
+ if (print_as_matrix) {
+ if (i == 0) {
+ for (j = 0; j < nfrom; j++) {
+ if (j == 0)
+ fprintf(stdout, " ");
+ fprintf(stdout, "|%d", Near[j].to_cat);
}
+ fprintf(stdout, "\n");
+ }
+ if (i % nfrom == 0) {
+ fprintf(stdout, "%d", Near[i].from_cat);
+ for (j = 0; j < nfrom; j++) {
+ print_upload(Near, Upload, i + j, &cvarr, catval);
+ }
+ fprintf(stdout, "\n");
}
- j++;
}
- fprintf(stdout, "\n" );
+ else {
+ fprintf(stdout, "%d", Near[i].from_cat );
+ print_upload(Near, Upload, i, &cvarr, catval);
+ fprintf(stdout, "\n" );
+ }
} else if ( all ) { /* insert new record */
sprintf (buf1, "insert into %s values ( %d ", table_opt->answer, Near[i].from_cat);
db_set_string (&stmt, buf1);
@@ -915,7 +891,8 @@
}
} else { /* update table */
/* check if exists in table */
- cex = (int *) bsearch((void *) &(Near[i].from_cat), catexist, ncatexist, sizeof(int), cmp_exist);
+ cex = (int *) bsearch((void *) &(Near[i].from_cat), catexist, ncatexist,
+ sizeof(int), cmp_exist);
if ( cex == NULL ){ /* cat does not exist in DB */
update_notexist++;
continue;
@@ -1021,11 +998,11 @@
db_free_string (&stmt);
/* print stats */
- if ( all ) {
+ if ( all && table_opt->answer) {
G_message(_("%d distances calculated"), count);
G_message(_("%d records inserted"), update_ok);
G_message(_("%d insert errors"), update_err);
- } else {
+ } else if (!all) {
G_message(_("%d categories read from the map"), nfcats);
G_message(_("%d categories exist in the table"), ncatexist);
G_message(_("%d categories read from the map exist in the table"), update_exist);
@@ -1063,6 +1040,25 @@
return 0;
}
+static int cmp_near_to (const void *pa, const void *pb) {
+ NEAR *p1 = (NEAR *) pa;
+ NEAR *p2 = (NEAR *) pb;
+
+ if(p1->from_cat < p2->from_cat)
+ return -1;
+
+ if(p1->from_cat > p2->from_cat)
+ return 1;
+
+ if(p1->to_cat < p2->to_cat)
+ return -1;
+
+ if(p1->to_cat > p2->to_cat)
+ return 1;
+
+ return 0;
+}
+
static int cmp_exist ( const void *pa, const void *pb)
{
@@ -1071,5 +1067,81 @@
if( *p1 < *p2 ) return -1;
if( *p1 > *p2) return 1;
+ return 0;
+}
+
+/*
+ print out upload values
+*/
+static int print_upload(NEAR *Near, UPLOAD *Upload, int i,
+ dbCatValArray *cvarr, dbCatVal *catval)
+{
+ int j;
+
+ j = 0;
+ while ( Upload[j].upload != END ) {
+ if ( Near[i].count == 0 ) { /* no nearest found */
+ fprintf(stdout, "|null" );
+ } else {
+ switch ( Upload[j].upload ) {
+ case CAT:
+ if ( Near[i].to_cat >= 0 )
+ fprintf(stdout, "|%d", Near[i].to_cat );
+ else
+ fprintf(stdout, "|null" );
+ break;
+ case DIST:
+ fprintf(stdout, "|%f", Near[i].dist );
+ break;
+ case FROM_X:
+ fprintf(stdout, "|%f", Near[i].from_x );
+ break;
+ case FROM_Y:
+ fprintf(stdout, "|%f", Near[i].from_y );
+ break;
+ case TO_X:
+ fprintf(stdout, "|%f", Near[i].to_x );
+ break;
+ case TO_Y:
+ fprintf(stdout, "|%f", Near[i].to_y );
+ break;
+ case FROM_ALONG:
+ fprintf(stdout, "|%f", Near[i].from_along );
+ break;
+ case TO_ALONG:
+ fprintf(stdout, "|%f", Near[i].to_along );
+ break;
+ case TO_ANGLE:
+ fprintf(stdout, "|%f", Near[i].to_angle );
+ break;
+ case TO_ATTR:
+ if ( catval ) {
+ switch (cvarr->ctype) {
+ case DB_C_TYPE_INT:
+ fprintf(stdout, "|%d", catval->val.i );
+ break;
+
+ case DB_C_TYPE_DOUBLE:
+ fprintf(stdout, "|%.15e", catval->val.d );
+ break;
+
+ case DB_C_TYPE_STRING:
+ fprintf(stdout, "|%s", db_get_string(catval->val.s) );
+ break;
+
+ case DB_C_TYPE_DATETIME:
+ /* TODO: formating datetime */
+ fprintf(stdout, "|" );
+ break;
+ }
+ } else {
+ fprintf(stdout, "|null" );
+ }
+ break;
+ }
+ }
+ j++;
+ }
+
return 0;
}
More information about the grass-commit
mailing list