[GRASS-SVN] r53387 - grass/trunk/vector/v.distance
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Oct 13 05:50:39 PDT 2012
Author: mmetz
Date: 2012-10-13 05:50:39 -0700 (Sat, 13 Oct 2012)
New Revision: 53387
Added:
grass/trunk/vector/v.distance/distance.c
Modified:
grass/trunk/vector/v.distance/local_proto.h
grass/trunk/vector/v.distance/main.c
grass/trunk/vector/v.distance/v.distance.html
Log:
v.distance: any feature to any feature
Added: grass/trunk/vector/v.distance/distance.c
===================================================================
--- grass/trunk/vector/v.distance/distance.c (rev 0)
+++ grass/trunk/vector/v.distance/distance.c 2012-10-13 12:50:39 UTC (rev 53387)
@@ -0,0 +1,329 @@
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/vector.h>
+#include "local_proto.h"
+
+/* TODO: geodesic distance for latlong */
+
+int get_line_box(const struct line_pnts *Points,
+ struct bound_box *box)
+{
+ int i;
+
+ if (Points->n_points == 0) {
+ box->E = box->W = box->N = box->S = box->T = box->B = 0.0 / 0.0;
+ return 0;
+ }
+
+ box->E = box->W = Points->x[0];
+ box->N = box->S = Points->y[0];
+ box->T = box->B = Points->z[0];
+
+ for (i = 1; i < Points->n_points; i++) {
+ if (box->E < Points->x[i])
+ box->E = Points->x[i];
+ if (box->W > Points->x[i])
+ box->W = Points->x[i];
+ if (box->N < Points->y[i])
+ box->N = Points->y[i];
+ if (box->S > Points->y[i])
+ box->S = Points->y[i];
+ if (box->T < Points->z[i])
+ box->T = Points->z[i];
+ if (box->B > Points->z[i])
+ box->B = Points->z[i];
+ }
+
+ return 1;
+}
+
+/* calculate distance parameters between two primitives
+ * return 1 point to point
+ * return 2 point to line
+ * return 1 line to line
+ */
+int line2line(struct line_pnts *FPoints, int ftype,
+ struct line_pnts *TPoints, int ttype,
+ double *fx, double *fy, double *fz,
+ double *falong, double *fangle,
+ double *tx, double *ty, double *tz,
+ double *talong, double *tangle,
+ double *dist,
+ int with_z,
+ int geodesic)
+{
+ int i, fseg, tseg, tmp_seg;
+ double tmp_dist, tmp_x, tmp_y, tmp_z, tmp_along;
+ int ret = 1;
+ static struct line_pnts *iPoints = NULL;
+
+ if (!iPoints)
+ iPoints = Vect_new_line_struct();
+
+ *dist = PORT_DOUBLE_MAX;
+
+ /* fangle and tangle are angles in radians, counter clockwise from x axis
+ * initialize to invalid angle */
+ *fangle = *tangle = -9.;
+ *falong = *talong = 0.;
+
+ *fx = FPoints->x[0];
+ *fy = FPoints->y[0];
+ *fz = FPoints->z[0];
+
+ *tx = TPoints->x[0];
+ *ty = TPoints->y[0];
+ *tz = TPoints->z[0];
+
+ /* point -> point */
+ if ((ftype & GV_POINTS) && (ttype & GV_POINTS)) {
+ Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0],
+ FPoints->z[0], with_z, tx, ty,tz, dist,
+ NULL, talong);
+
+ }
+
+ /* point -> line and line -> line */
+ if ((ttype & GV_LINES)) {
+
+ tseg = 1;
+ /* calculate the min distance between each point in fline with tline */
+ for (i = 0; i < FPoints->n_points; i++) {
+
+ tmp_seg = Vect_line_distance(TPoints, FPoints->x[i],
+ FPoints->y[i], FPoints->z[i],
+ with_z, &tmp_x, &tmp_y, &tmp_z,
+ &tmp_dist, NULL, &tmp_along);
+ if (*dist > tmp_dist) {
+ *dist = tmp_dist;
+ *tx = tmp_x;
+ *ty = tmp_y;
+ *tz = tmp_z;
+ *talong = tmp_along;
+ tseg = tmp_seg;
+ }
+ }
+ Vect_point_on_line(TPoints, *talong, NULL, NULL, NULL,
+ tangle, NULL);
+ ret++;
+ }
+
+ /* line -> point and line -> line */
+ if (ftype & GV_LINES) {
+
+ fseg = 1;
+
+ /* calculate the min distance between each point in tline with fline */
+ for (i = 0; i < TPoints->n_points; i++) {
+
+ tmp_seg = Vect_line_distance(FPoints, TPoints->x[i],
+ TPoints->y[i], TPoints->z[i],
+ with_z, &tmp_x, &tmp_y, &tmp_z,
+ &tmp_dist, NULL, &tmp_along);
+ if (*dist > tmp_dist) {
+ *dist = tmp_dist;
+ *fx = tmp_x;
+ *fy = tmp_y;
+ *fz = tmp_z;
+ *falong = tmp_along;
+ fseg = tmp_seg;
+ }
+ }
+ Vect_point_on_line(FPoints, *falong, NULL, NULL, NULL,
+ fangle, NULL);
+ ret++;
+
+ if ((ttype & GV_LINES) && *dist > 0) {
+ /* check for line intersection */
+ struct bound_box fbox, tbox;
+
+ get_line_box(FPoints, &fbox);
+ get_line_box(TPoints, &tbox);
+
+ if (Vect_box_overlap(&fbox, &tbox)) {
+ Vect_reset_line(iPoints);
+ Vect_line_get_intersections(FPoints, TPoints, iPoints, with_z);
+ if (iPoints->n_points) {
+ *dist = 0;
+ *fx = *tx = iPoints->x[0];
+ *fy = *ty = iPoints->y[0];
+ *fz = *tz = iPoints->z[0];
+
+ /* falong, talong */
+ Vect_line_distance(FPoints, iPoints->x[0],
+ iPoints->y[0], iPoints->z[0],
+ with_z, NULL, NULL, NULL,
+ NULL, NULL, falong);
+ Vect_line_distance(TPoints, iPoints->x[0],
+ iPoints->y[0], iPoints->z[0],
+ with_z, NULL, NULL, NULL,
+ NULL, NULL, talong);
+ /* fangle, tangle */
+ Vect_point_on_line(FPoints, *falong, NULL, NULL, NULL,
+ fangle, NULL);
+ Vect_point_on_line(TPoints, *talong, NULL, NULL, NULL,
+ tangle, NULL);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+/* shortest distance between line and area
+ * return 1 inside area
+ * return 2 inside isle of area
+ * return 3 outside area */
+int line2area(const struct Map_info *To,
+ struct line_pnts *Points, int type,
+ int area, const struct bound_box *abox,
+ double *fx, double *fy, double *fz,
+ double *falong, double *fangle,
+ double *tx, double *ty, double *tz,
+ double *talong, double *tangle,
+ double *dist,
+ int with_z,
+ int geodesic)
+{
+ int i, j;
+ double tmp_dist;
+ int isle, nisles;
+ static struct line_pnts *aPoints = NULL;
+ static struct line_pnts **iPoints = NULL;
+ static struct bound_box *ibox = NULL;
+ static int isle_alloc = 0;
+
+ if (!aPoints)
+ aPoints = Vect_new_line_struct();
+
+ *dist = PORT_DOUBLE_MAX;
+
+ /* fangle and tangle are angles in radians, counter clockwise from x axis
+ * initialize to invalid angle */
+ *fangle = *tangle = -9.;
+ *falong = *talong = 0.;
+
+ *fx = Points->x[0];
+ *fy = Points->y[0];
+ *fz = Points->z[0];
+
+ *tx = Points->x[0];
+ *ty = Points->y[0];
+ *tz = Points->z[0];
+
+ Vect_get_area_points(To, area, aPoints);
+ nisles = Vect_get_area_num_isles(To, area);
+
+ if (nisles > isle_alloc) {
+ iPoints = G_realloc(iPoints, nisles * sizeof(struct line_pnts *));
+ ibox = G_realloc(ibox, nisles * sizeof(struct bound_box));
+ for (i = isle_alloc; i < nisles; i++)
+ iPoints[i] = Vect_new_line_struct();
+ isle_alloc = nisles;
+ }
+ for (i = 0; i < nisles; i++) {
+ isle = Vect_get_area_isle(To, area, i);
+ Vect_get_isle_points(To, isle, iPoints[i]);
+ Vect_get_isle_box(To, isle, &ibox[i]);
+ }
+
+ /* inside area ? */
+
+ for (i = 0; i < Points->n_points; i++) {
+ if (Vect_point_in_box(Points->x[i], Points->y[i],
+ Points->z[i], abox)) {
+
+ int poly;
+
+ poly = Vect_point_in_poly(Points->x[i], Points->y[i], aPoints);
+
+ /* exactly on boundary */
+ if (poly == 2) {
+ line2line(Points, type, aPoints, GV_BOUNDARY,
+ fx, fy, fz, falong, fangle,
+ tx, ty, tz, talong, tangle,
+ dist, with_z, geodesic);
+
+ return 1;
+ }
+ /* inside */
+ else if (poly == 1) {
+ int inside = 0;
+
+ for (j = 0; j < nisles; j++) {
+ if (Vect_point_in_box(Points->x[i], Points->y[i], Points->z[i],
+ &ibox[j])) {
+
+ poly = Vect_point_in_poly(Points->x[i], Points->y[i], iPoints[j]);
+
+ /* inside or exactly on boundary */
+ if (poly > 0) {
+ double tmp_fx, tmp_fy, tmp_fz, tmp_fangle, tmp_falong;
+ double tmp_tx, tmp_ty, tmp_tz, tmp_tangle, tmp_talong;
+
+ line2line(Points, type, iPoints[j], GV_BOUNDARY,
+ &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
+ &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
+ &tmp_dist, with_z, geodesic);
+
+ if (*dist > tmp_dist) {
+ *dist = tmp_dist;
+
+ *fx = tmp_fx;
+ *fy = tmp_fy;
+ *fz = tmp_fz;
+ *falong = tmp_falong;
+ *fangle = tmp_fangle;
+
+ *tx = tmp_tx;
+ *ty = tmp_ty;
+ *tz = tmp_tz;
+ *talong = tmp_talong;
+ *tangle = tmp_tangle;
+ }
+
+ if (poly == 1)
+ inside = 1;
+
+ }
+ }
+ if (*dist == 0)
+ break;
+ }
+ /* inside area (inside outer ring, outside inner rings) */
+ if (!inside) {
+ *fx = Points->x[i];
+ *fy = Points->y[i];
+ *fz = Points->z[i];
+
+ *tx = Points->x[i];
+ *ty = Points->y[i];
+ *tz = Points->z[i];
+
+ *dist = 0;
+
+ return 1;
+ }
+ /* inside one of the islands */
+ else
+ return 2;
+ } /* end inside outer ring */
+ }
+ /* not possible */
+ if (*dist == 0)
+ return 1;
+ }
+
+ /* line is outside area */
+
+ line2line(Points, type, aPoints, GV_BOUNDARY,
+ fx, fy, fz, falong, fangle,
+ tx, ty, tz, talong, tangle,
+ dist, with_z, geodesic);
+
+ if (*dist == 0)
+ return 1;
+
+ return 3;
+}
Property changes on: grass/trunk/vector/v.distance/distance.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Modified: grass/trunk/vector/v.distance/local_proto.h
===================================================================
--- grass/trunk/vector/v.distance/local_proto.h 2012-10-13 11:56:04 UTC (rev 53386)
+++ grass/trunk/vector/v.distance/local_proto.h 2012-10-13 12:50:39 UTC (rev 53387)
@@ -1,3 +1,4 @@
+#include <grass/vector.h>
#include <grass/dbmi.h>
/* define codes for characteristics of relation between two nearest features */
@@ -19,8 +20,10 @@
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_x, from_y, from_z; /* coordinates of nearest 'from' point */
+ double to_x, to_y, to_z; /* coordinates of nearest 'to' point */
double from_along, to_along; /* distance along a linear feature to the nearest point */
+ double from_angle; /* angle of linear feature in nearest point */
double to_angle; /* angle of linear feature in nearest point */
double dist; /* distance to nearest feature */
} NEAR;
@@ -36,5 +39,29 @@
int cmp_near(const void *, const void *);
int cmp_near_to(const void *, const void *);
int cmp_exist(const void *, const void *);
+
+/* distance.c */
+int get_line_box(const struct line_pnts *Points,
+ struct bound_box *box);
+int line2line(struct line_pnts *FPoints, int ftype,
+ struct line_pnts *TPoints, int ttype,
+ double *fx, double *fy, double *fz,
+ double *falong, double *fangle,
+ double *tx, double *ty, double *tz,
+ double *talong, double *tangle,
+ double *dist,
+ int with_z,
+ int geodesic);
+int line2area(const struct Map_info *To,
+ struct line_pnts *Points, int type,
+ int area, const struct bound_box *abox,
+ double *fx, double *fy, double *fz,
+ double *falong, double *fangle,
+ double *tx, double *ty, double *tz,
+ double *talong, double *tangle,
+ double *dist,
+ int with_z,
+ int geodesic);
+
/* print.c */
int print_upload(NEAR *, UPLOAD *, int, dbCatValArray *, dbCatVal *);
Modified: grass/trunk/vector/v.distance/main.c
===================================================================
--- grass/trunk/vector/v.distance/main.c 2012-10-13 11:56:04 UTC (rev 53386)
+++ grass/trunk/vector/v.distance/main.c 2012-10-13 12:50:39 UTC (rev 53387)
@@ -9,10 +9,11 @@
* - updated to 5.7 by Radim Blazek 2003
* - OGR support by Martin Landa <landa.martin gmail.com> (2009)
* - speed-up for dmax != 0 Markus Metz 2010
+ * - support all features Markus Metz 2012
*
* PURPOSE: Calculates distance from a point to nearest feature in vector layer.
*
- * COPYRIGHT: (C) 2002-2010 by the GRASS Development Team
+ * COPYRIGHT: (C) 2002-2012 by the GRASS Development Team
*
* This program is free software under the
* GNU General Public License (>=v2).
@@ -34,7 +35,7 @@
int main(int argc, char *argv[])
{
- int i, j, k;
+ int i, j;
int print_as_matrix; /* only for do_all=TRUE */
int do_all; /* calculate from each to each within the threshold */
struct GModule *module;
@@ -49,7 +50,7 @@
} flag;
char *desc;
struct Map_info From, To, Out, *Outp;
- int from_type, to_type, from_field, to_field;
+ int from_type, to_type, from_field, to_field, with_z;
double max, min;
double *max_step;
int n_max_steps, curr_step;
@@ -58,10 +59,12 @@
NEAR *Near, *near;
int anear; /* allocated space, used only for do_all */
UPLOAD *Upload; /* zero terminated */
- int ftype, fcat, tcat, count;
- int nfrom, nto, nfcats, fline, tline, tseg, tarea, area, isle, nisles;
- double tx, ty, tz, dist, talong, tmp_tx, tmp_ty, tmp_tz, tmp_dist,
- tmp_talong;
+ int ftype, ttype, fcat, nfcats, tcat, count, fline, tfeature;
+ int nfrom, nfromlines, nfromareas, nto, ntolines, ntoareas;
+ int tarea, area, isle, nisles, nlines;
+ double fx, fy, fz, falong, fangle, tx, ty, tz, talong, tangle, dist;
+ double tmp_fx, tmp_fy, tmp_fz, tmp_falong, tmp_fangle, tmp_dist;
+ double tmp_tx, tmp_ty, tmp_tz, tmp_talong, tmp_tangle;
struct field_info *Fi, *toFi;
dbString stmt, dbstr;
dbDriver *driver, *to_driver;
@@ -69,8 +72,8 @@
char buf1[2000], buf2[2000], to_attr_sqltype[256];
int update_ok, update_err, update_exist, update_notexist, update_dupl,
update_notfound, sqltype;
- struct boxlist *List;
- struct bound_box box;
+ struct boxlist *lList, *aList;
+ struct bound_box fbox, box;
dbCatValArray cvarr;
dbColumn *column;
@@ -100,8 +103,8 @@
opt.from_type = G_define_standard_option(G_OPT_V_TYPE);
opt.from_type->key = "from_type";
- opt.from_type->options = "point,centroid";
- opt.from_type->answer = "point";
+ opt.from_type->options = "point,line,boundary,centroid,area";
+ opt.from_type->answer = "point,line,area";
opt.from_type->label = _("Feature type (from)");
opt.from_type->guisection = _("From");
@@ -289,16 +292,36 @@
from_field = Vect_get_field_number(&From, opt.from_field->answer);
- if (Vect_get_num_primitives(&From, GV_POINTS) < 1) {
+ nfromlines = Vect_get_num_primitives(&From, from_type);
+ nfromareas = 0;
+ if (from_type & GV_AREA)
+ nfromareas = Vect_get_num_areas(&From);
+
+ nfrom = nfromlines + nfromareas;
+ if (nfrom < 1) {
const char *name = Vect_get_full_name(&From);
Vect_close(&From);
- G_fatal_error(_("No points/centroids found in <%s>"), name);
+ G_fatal_error(_("No features of selected type found in <%s>"), name);
}
/* Open 'to' vector */
Vect_set_open_level(2);
Vect_open_old2(&To, opt.to->answer, "", opt.to_field->answer);
+ ntolines = Vect_get_num_primitives(&To, from_type);
+ ntoareas = 0;
+ if (to_type & GV_AREA)
+ ntoareas = Vect_get_num_areas(&To);
+
+ nto = ntolines + ntoareas;
+ if (nto < 1) {
+ const char *name = Vect_get_full_name(&To);
+ Vect_close(&From);
+ Vect_close(&To);
+ G_fatal_error(_("No features of selected type found in <%s>"), name);
+ }
+ with_z = (Vect_is_3d(&From) && Vect_is_3d(&To));
+
to_field = Vect_get_field_number(&To, opt.to_field->answer);
/* Open output vector */
@@ -317,7 +340,6 @@
if (max != 0) {
struct bound_box fbox, tbox;
double dx, dy, dz, tmp_max;
- int n_features = 0;
Vect_get_map_box(&From, &fbox);
Vect_get_map_box(&To, &tbox);
@@ -339,35 +361,24 @@
/* with max > 0 but max <<< tmp_max, 2 steps are sufficient, first 0 then max
* a reasonable number of steps also depends on the number of features in To
* e.g. only one area in To, no need to step */
- nto = Vect_get_num_lines(&To);
- for (tline = 1; tline <= nto; tline++) {
- /* TODO: Vect_get_line_type() */
- n_features += ((to_type & To.plus.Line[tline]->type) != 0);
- }
- if (to_type & GV_AREA) {
- if (Vect_get_num_areas(&To) > n_features)
- n_features = Vect_get_num_areas(&To);
- }
- if (n_features == 0)
- G_fatal_error(_("No features of selected type in To vector <%s>"),
- opt.to->answer);
- n_max_steps = sqrt(n_features) * max / tmp_max;
+
+ n_max_steps = sqrt(nto) * max / tmp_max;
/* max 9 steps from testing */
if (n_max_steps > 9)
n_max_steps = 9;
if (n_max_steps < 2)
n_max_steps = 2;
- if (n_max_steps > n_features)
- n_max_steps = n_features;
+ if (n_max_steps > nto)
+ n_max_steps = nto;
G_debug(2, "max = %f", max);
G_debug(2, "maximum reasonable search distance = %f", tmp_max);
- G_debug(2, "n_features = %d", n_features);
+ G_debug(2, "n 'to' features = %d", nto);
G_debug(2, "n_max_steps = %d", n_max_steps);
}
if (min > max)
- G_fatal_error("dmin can not be larger than dmax");
+ G_fatal_error(_("dmin can not be larger than dmax"));
if (n_max_steps > 1) {
/* set up steps to increase search box */
@@ -391,6 +402,7 @@
db_init_string(&stmt);
db_init_string(&dbstr);
driver = NULL;
+ Fi = NULL;
if (!flag.print->answer && !do_all) {
Fi = Vect_get_field(&From, from_field);
@@ -424,6 +436,7 @@
}
to_driver = NULL;
+ toFi = NULL;
if (opt.to_column->answer) {
toFi = Vect_get_field(&To, to_field);
if (toFi == NULL)
@@ -496,24 +509,19 @@
TPoints = Vect_new_line_struct();
FCats = Vect_new_cats_struct();
TCats = Vect_new_cats_struct();
- List = Vect_new_boxlist(1);
+ lList = Vect_new_boxlist(1); /* line list */
+ aList = Vect_new_boxlist(1); /* area list */
/* Allocate space ( may be more than needed (duplicate cats and elements without cats) ) */
- nfrom = Vect_get_num_lines(&From);
- nto = Vect_get_num_lines(&To);
- if (do_all) {
- /* Be careful with do_all, it can easily run out of memory */
- anear = 2 * nfrom;
- Near = (NEAR *) G_calloc(anear, sizeof(NEAR));
- }
- else {
- Near = (NEAR *) G_calloc(nfrom, sizeof(NEAR));
- }
+ /* Be careful with do_all, it can easily run out of memory */
+ anear = nfrom;
+ Near = (NEAR *) G_calloc(nfrom, sizeof(NEAR));
/* Read all cats from 'from' */
+ nfcats = 0;
if (!do_all) {
- nfcats = 0;
- for (i = 1; i <= nfrom; i++) {
+ nlines = Vect_get_num_lines(&From);
+ for (i = 1; i <= nlines; i++) {
ftype = Vect_read_line(&From, NULL, FCats, i);
/* This keeps also categories of areas for future (if area s in from_type) */
@@ -525,22 +533,28 @@
if (fcat < 0)
continue;
Near[nfcats].from_cat = fcat;
+ Near[nfcats].dist = -1;
+ Near[nfcats].count = 0;
nfcats++;
}
G_debug(1, "%d cats loaded from vector (including duplicates)",
nfcats);
+
+ if (nfcats == 0)
+ G_fatal_error(_("No categories for 'from' for slected type and layer"));
+
/* Sort by cats and remove duplicates */
qsort((void *)Near, nfcats, sizeof(NEAR), cmp_near);
/* remove duplicates */
+ j = 1;
for (i = 1; i < nfcats; i++) {
- if (Near[i].from_cat == Near[i - 1].from_cat) {
- for (j = i; j < nfcats - 1; j++) {
- Near[j].from_cat = Near[j + 1].from_cat;
- }
- nfcats--;
+ if (Near[i].from_cat != Near[j - 1].from_cat) {
+ Near[j].from_cat = Near[i].from_cat;
+ j++;
}
}
+ nfcats = j;
G_debug(1, "%d cats loaded from vector (unique)", nfcats);
}
@@ -549,20 +563,15 @@
/* Note: as from_type is restricted to GV_POINTS (for now) everything is simple */
count = 0; /* count of distances in 'do_all' mode */
- /* Find nearest lines */
- if (to_type & (GV_POINTS | GV_LINES)) {
- struct line_pnts *LLPoints;
+ /* Find nearest features for 'from' lines */
+ if (nfromlines) {
+ G_message(_("Finding nearest features..."));
+
+ near = NULL;
+ nlines = Vect_get_num_lines(&From);
- if (G_projection() == PROJECTION_LL) {
- LLPoints = Vect_new_line_struct();
- }
- else {
- LLPoints = NULL;
- }
- G_message(_("Finding nearest feature..."));
- for (fline = 1; fline <= nfrom; fline++) {
+ for (fline = 1; fline <= nlines; fline++) {
int tmp_tcat;
- double tmp_tangle, tangle;
double tmp_min = (min < 0 ? 0 : min);
double box_edge = 0;
int done = FALSE;
@@ -571,99 +580,162 @@
G_debug(3, "fline = %d", fline);
G_percent(fline, nfrom, 2);
- ftype = Vect_read_line(&From, FPoints, FCats, fline);
+ ftype = Vect_get_line_type(&From, fline);
if (!(ftype & from_type))
continue;
+ Vect_read_line(&From, FPoints, FCats, fline);
Vect_cat_get(FCats, from_field, &fcat);
if (fcat < 0 && !do_all)
continue;
+ get_line_box(FPoints, &fbox);
+
+ if (!do_all) {
+ /* find near by 'from' cat */
+ near = (NEAR *) bsearch((void *)&fcat, Near, nfcats,
+ sizeof(NEAR), cmp_near);
+ }
+
+ dist = PORT_DOUBLE_MAX; /* distance to nearest 'to' feature */
+
while (!done) {
done = TRUE;
+ tfeature = 0; /* id of nearest 'to' feature */
+
if (!do_all) {
/* enlarge search box until we get a hit */
/* the objective is to enlarge the search box
* in the first iterations just a little bit
* to keep the number of hits low */
- Vect_reset_boxlist(List);
while (curr_step < n_max_steps) {
box_edge = max_step[curr_step];
if (box_edge < tmp_min)
continue;
- box.E = FPoints->x[0] + box_edge;
- box.W = FPoints->x[0] - box_edge;
- box.N = FPoints->y[0] + box_edge;
- box.S = FPoints->y[0] - box_edge;
+ box.E = fbox.E + box_edge;
+ box.W = fbox.W - box_edge;
+ box.N = fbox.N + box_edge;
+ box.S = fbox.S - box_edge;
box.T = PORT_DOUBLE_MAX;
box.B = -PORT_DOUBLE_MAX;
- Vect_select_lines_by_box(&To, &box, to_type, List);
+ if (ntolines)
+ Vect_select_lines_by_box(&To, &box, to_type, lList);
+ if (ntoareas)
+ Vect_select_areas_by_box(&To, &box, aList);
curr_step++;
- if (List->n_values > 0)
+ if (lList->n_values > 0 || aList->n_values > 0)
break;
}
}
else {
- box.E = FPoints->x[0] + max;
- box.W = FPoints->x[0] - max;
- box.N = FPoints->y[0] + max;
- box.S = FPoints->y[0] - max;
+ box.E = fbox.E + max;
+ box.W = fbox.W - max;
+ box.N = fbox.N + max;
+ box.S = fbox.S - max;
box.T = PORT_DOUBLE_MAX;
box.B = -PORT_DOUBLE_MAX;
- Vect_select_lines_by_box(&To, &box, to_type, List);
+ if (ntolines)
+ Vect_select_lines_by_box(&To, &box, to_type, lList);
+ if (ntoareas)
+ Vect_select_areas_by_box(&To, &box, aList);
}
- G_debug(3, " %d lines in box", List->n_values);
+ G_debug(3, " %d lines in box", lList->n_values);
- tline = 0;
- dist = PORT_DOUBLE_MAX;
- for (i = 0; i < List->n_values; i++) {
+ for (i = 0; i < lList->n_values; i++) {
tmp_tcat = -1;
- Vect_read_line(&To, TPoints, TCats, List->id[i]);
+ ttype = Vect_read_line(&To, TPoints, TCats, lList->id[i]);
- tseg =
- Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0],
- FPoints->z[0], (Vect_is_3d(&From) &&
- Vect_is_3d(&To)) ?
- WITH_Z : WITHOUT_Z, &tmp_tx, &tmp_ty,
- &tmp_tz, &tmp_dist, NULL, &tmp_talong);
+ line2line(FPoints, ftype, TPoints, ttype,
+ &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
+ &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
+ &tmp_dist, with_z, 0);
- Vect_point_on_line(TPoints, tmp_talong, NULL, NULL, NULL,
- &tmp_tangle, NULL);
-
if (tmp_dist > max || tmp_dist < min)
continue; /* not in threshold */
/* TODO: more cats of the same field */
Vect_cat_get(TCats, to_field, &tmp_tcat);
- if (G_projection() == PROJECTION_LL) {
- /* calculate distances in meters not degrees (only 2D) */
- Vect_reset_line(LLPoints);
- Vect_append_point(LLPoints, FPoints->x[0], FPoints->y[0],
- FPoints->z[0]);
- Vect_append_point(LLPoints, tmp_tx, tmp_ty, tmp_tz);
- tmp_dist = Vect_line_geodesic_length(LLPoints);
- Vect_reset_line(LLPoints);
- for (k = 0; k < tseg; k++)
- Vect_append_point(LLPoints, TPoints->x[k],
- TPoints->y[k], TPoints->z[k]);
- Vect_append_point(LLPoints, tmp_tx, tmp_ty, tmp_tz);
- tmp_talong = Vect_line_geodesic_length(LLPoints);
+
+ G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist,
+ tmp_tcat);
+
+ if (do_all) {
+ if (anear <= count) {
+ anear += 10 + nto / 10;
+ Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR));
+ if (!Near)
+ G_fatal_error(_("Out of memory!"));
+ }
+ near = &(Near[count]);
+
+ /* store info about relation */
+ near->from_cat = fcat;
+ near->to_cat = tmp_tcat; /* -1 is OK */
+ near->dist = tmp_dist;
+ near->from_x = tmp_fx;
+ near->from_y = tmp_fy;
+ near->from_z = tmp_fz;
+ near->from_along = tmp_falong; /* 0 for points */
+ near->from_angle = tmp_fangle;
+ near->to_x = tmp_tx;
+ near->to_y = tmp_ty;
+ near->to_z = tmp_tz;
+ near->to_along = tmp_talong; /* 0 for points */
+ near->to_angle = tmp_tangle;
+ near->count++;
+ count++;
}
+ else {
+ if (tfeature == 0 || (tmp_dist < dist)) {
+ tfeature = lList->id[i];
+ tcat = tmp_tcat;
+ dist = tmp_dist;
+ fx = tmp_fx;
+ fy = tmp_fy;
+ fz = tmp_fz;
+ falong = tmp_falong;
+ fangle = tmp_fangle;
+ tx = tmp_tx;
+ ty = tmp_ty;
+ tz = tmp_tz;
+ talong = tmp_talong;
+ tangle = tmp_tangle;
+ }
+ }
+ }
+ G_debug(3, " %d areas in box", aList->n_values);
+
+ for (i = 0; i < aList->n_values; i++) {
+ tmp_tcat = -1;
+
+ line2area(&To, FPoints, ftype, aList->id[i], &aList->box[i],
+ &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
+ &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
+ &tmp_dist, with_z, 0);
+
+ if (tmp_dist > max || tmp_dist < min)
+ continue; /* not in threshold */
+
+ /* TODO: more cats of the same field */
+ Vect_cat_get(TCats, to_field, &tmp_tcat);
+
G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist,
tmp_tcat);
if (do_all) {
if (anear <= count) {
- anear += 10 + nfrom / 10;
+ anear += 10 + nto / 10;
Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR));
+ if (!Near)
+ G_fatal_error(_("Out of memory!"));
}
near = &(Near[count]);
@@ -671,9 +743,11 @@
near->from_cat = fcat;
near->to_cat = tmp_tcat; /* -1 is OK */
near->dist = tmp_dist;
- near->from_x = FPoints->x[0];
- near->from_y = FPoints->y[0];
- near->from_z = FPoints->z[0];
+ near->from_x = tmp_fx;
+ near->from_y = tmp_fy;
+ near->from_z = tmp_fz;
+ near->from_along = tmp_falong; /* 0 for points */
+ near->from_angle = tmp_fangle;
near->to_x = tmp_tx;
near->to_y = tmp_ty;
near->to_z = tmp_tz;
@@ -683,10 +757,15 @@
count++;
}
else {
- if (tline == 0 || (tmp_dist < dist)) {
- tline = List->id[i];
+ if (tfeature == 0 || (tmp_dist < dist)) {
+ tfeature = aList->id[i];
tcat = tmp_tcat;
dist = tmp_dist;
+ fx = tmp_fx;
+ fy = tmp_fy;
+ fz = tmp_fz;
+ falong = tmp_falong;
+ fangle = tmp_fangle;
tx = tmp_tx;
ty = tmp_ty;
tz = tmp_tz;
@@ -700,31 +779,29 @@
if (!do_all && curr_step < n_max_steps) {
/* enlarging the search box is possible */
- if (tline > 0 && dist > box_edge) {
+ if (tfeature > 0 && dist > box_edge) {
/* line found but distance > search edge:
* line bbox overlaps with search box, line itself is outside search box */
done = FALSE;
}
- else if (tline == 0) {
+ else if (tfeature == 0) {
/* no line within max dist, but search box can still be enlarged */
done = FALSE;
}
}
- if (done && !do_all && tline > 0) {
- /* find near by cat */
- near =
- (NEAR *) bsearch((void *)&fcat, Near, nfcats,
- sizeof(NEAR), cmp_near);
+ if (done && !do_all && tfeature > 0) {
- G_debug(4, " near.from_cat = %d near.count = %d",
+ G_debug(4, " near->from_cat = %d near->count = %d",
near->from_cat, near->count);
/* store info about relation */
if (near->count == 0 || near->dist > dist) {
near->to_cat = tcat; /* -1 is OK */
near->dist = dist;
- near->from_x = FPoints->x[0];
- near->from_y = FPoints->y[0];
- near->from_z = FPoints->z[0];
+ near->from_x = fx;
+ near->from_y = fy;
+ near->from_z = fz;
+ near->from_along = falong; /* 0 for points */
+ near->from_angle = fangle;
near->to_x = tx;
near->to_y = ty;
near->to_z = tz;
@@ -733,117 +810,223 @@
}
near->count++;
}
- } /* done */
- } /* next feature */
- if (LLPoints) {
- Vect_destroy_line_struct(LLPoints);
- }
+ } /* done searching 'to' */
+ } /* next from feature */
}
- /* Find nearest areas */
- if (to_type & GV_AREA) {
+ /* Find nearest features for 'from' areas */
+ /* the code is pretty much identical to the one for lines */
+ if (nfromareas) {
- G_message(_("Finding nearest areas..."));
- for (fline = 1; fline <= nfrom; fline++) {
+ near = NULL;
+
+ G_message(_("Finding nearest features for areas..."));
+ for (area = 1; area <= nfromareas; area++) {
+ int tmp_tcat;
double tmp_min = (min < 0 ? 0 : min);
double box_edge = 0;
int done = FALSE;
curr_step = 0;
- G_debug(3, "fline = %d", fline);
- G_percent(fline, nfrom, 2);
- ftype = Vect_read_line(&From, FPoints, FCats, fline);
- if (!(ftype & from_type))
- continue;
+ G_debug(3, "farea = %d", area);
+ G_percent(area, nfromareas, 2);
+ Vect_get_area_cats(&From, area, FCats);
Vect_cat_get(FCats, from_field, &fcat);
if (fcat < 0 && !do_all)
continue;
+ Vect_get_area_box(&From, area, &fbox);
+ Vect_reset_line(FPoints);
+
+ if (!do_all) {
+ /* find near by 'from' cat */
+ near = (NEAR *) bsearch((void *)&fcat, Near, nfcats,
+ sizeof(NEAR), cmp_near);
+ }
+
+ dist = PORT_DOUBLE_MAX; /* distance to nearest 'to' feature */
+
while (!done) {
done = TRUE;
+ tfeature = 0; /* id of nearest 'to' feature */
+
if (!do_all) {
/* enlarge search box until we get a hit */
/* the objective is to enlarge the search box
* in the first iterations just a little bit
* to keep the number of hits low */
- Vect_reset_boxlist(List);
while (curr_step < n_max_steps) {
box_edge = max_step[curr_step];
if (box_edge < tmp_min)
continue;
- box.E = FPoints->x[0] + box_edge;
- box.W = FPoints->x[0] - box_edge;
- box.N = FPoints->y[0] + box_edge;
- box.S = FPoints->y[0] - box_edge;
+ box.E = fbox.E + box_edge;
+ box.W = fbox.W - box_edge;
+ box.N = fbox.N + box_edge;
+ box.S = fbox.S - box_edge;
box.T = PORT_DOUBLE_MAX;
box.B = -PORT_DOUBLE_MAX;
- Vect_select_areas_by_box(&To, &box, List);
+ if (ntolines)
+ Vect_select_lines_by_box(&To, &box, to_type, lList);
+ if (ntoareas)
+ Vect_select_areas_by_box(&To, &box, aList);
curr_step++;
- if (List->n_values > 0)
+ if (lList->n_values > 0 || aList->n_values > 0)
break;
}
}
else {
- box.E = FPoints->x[0] + max;
- box.W = FPoints->x[0] - max;
- box.N = FPoints->y[0] + max;
- box.S = FPoints->y[0] - max;
+ box.E = fbox.E + max;
+ box.W = fbox.W - max;
+ box.N = fbox.N + max;
+ box.S = fbox.S - max;
box.T = PORT_DOUBLE_MAX;
box.B = -PORT_DOUBLE_MAX;
- Vect_select_areas_by_box(&To, &box, List);
+ if (ntolines)
+ Vect_select_lines_by_box(&To, &box, to_type, lList);
+ if (ntoareas)
+ Vect_select_areas_by_box(&To, &box, aList);
}
- G_debug(4, "%d areas selected by box", List->n_values);
+ G_debug(3, " %d lines in box", lList->n_values);
+ for (i = 0; i < lList->n_values; i++) {
+ tmp_tcat = -1;
+ ttype = Vect_read_line(&To, TPoints, TCats, lList->id[i]);
+
+ /* area to line */
+ line2area(&From, TPoints, ttype, area, &fbox,
+ &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
+ &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
+ &tmp_dist, with_z, 0);
+
+ if (tmp_dist > max || tmp_dist < min)
+ continue; /* not in threshold */
+
+ /* TODO: more cats of the same field */
+ Vect_cat_get(TCats, to_field, &tmp_tcat);
+
+ G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist,
+ tmp_tcat);
+
+ if (do_all) {
+ if (anear <= count) {
+ anear += 10 + nto / 10;
+ Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR));
+ if (!Near)
+ G_fatal_error(_("Out of memory!"));
+ }
+ near = &(Near[count]);
+
+ /* store info about relation */
+ near->from_cat = fcat;
+ near->to_cat = tmp_tcat; /* -1 is OK */
+ near->dist = tmp_dist;
+ near->from_x = tmp_fx;
+ near->from_y = tmp_fy;
+ near->from_z = tmp_fz;
+ near->from_along = tmp_falong; /* 0 for points */
+ near->from_angle = tmp_fangle;
+ near->to_x = tmp_tx;
+ near->to_y = tmp_ty;
+ near->to_z = tmp_tz;
+ near->to_along = tmp_talong; /* 0 for points */
+ near->to_angle = tmp_tangle;
+ near->count++;
+ count++;
+ }
+ else {
+ if (tfeature == 0 || (tmp_dist < dist)) {
+ tfeature = lList->id[i];
+ tcat = tmp_tcat;
+ dist = tmp_dist;
+ fx = tmp_fx;
+ fy = tmp_fy;
+ fz = tmp_fz;
+ falong = tmp_falong;
+ fangle = tmp_fangle;
+ tx = tmp_tx;
+ ty = tmp_ty;
+ tz = tmp_tz;
+ talong = tmp_talong;
+ tangle = tmp_tangle;
+ }
+ }
+ }
+
+ G_debug(3, " %d areas in box", aList->n_values);
+
/* For each area in box check the distance */
- tarea = 0;
- dist = PORT_DOUBLE_MAX;
- for (i = 0; i < List->n_values; i++) {
- int tmp_tcat;
+ for (i = 0; i < aList->n_values; i++) {
+ int tmp_tcat, poly;
- area = List->id[i];
- G_debug(4, "%d: area %d", i, area);
- Vect_get_area_points(&To, area, TPoints);
+ tarea = aList->id[i];
+ G_debug(4, "%d: area %d", i, tarea);
+ Vect_get_area_points(&To, tarea, TPoints);
+
+ ttype = GV_BOUNDARY;
/* Find the distance to this area */
- if (Vect_point_in_area(FPoints->x[0], FPoints->y[0], &To, area, &List->box[i])) { /* in area */
- tmp_dist = 0;
- tmp_tx = FPoints->x[0];
- tmp_ty = FPoints->y[0];
- }
- else if (Vect_point_in_poly(FPoints->x[0], FPoints->y[0], TPoints) > 0) { /* in isle */
- nisles = Vect_get_area_num_isles(&To, area);
- for (j = 0; j < nisles; j++) {
- double tmp2_dist, tmp2_tx, tmp2_ty;
+ poly = line2area(&From, TPoints, ttype, area, &fbox,
+ &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
+ &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
+ &tmp_dist, with_z, 0);
- isle = Vect_get_area_isle(&To, area, j);
- Vect_get_isle_points(&To, isle, TPoints);
- Vect_line_distance(TPoints, FPoints->x[0],
- FPoints->y[0], FPoints->z[0],
- WITHOUT_Z, &tmp2_tx, &tmp2_ty,
- NULL, &tmp2_dist, NULL, NULL);
+ if (poly == 3) {
+ /* 'to' area is outside 'from' area,
+ * check if 'from' area is inside 'to' area */
+ poly = 0;
+ /* boxes must overlap */
+ if (Vect_box_overlap(&fbox, &aList->box[i])) {
+ if (FPoints->n_points == 0)
+ Vect_get_area_points(&From, area, FPoints);
+ for (j = 0; j < FPoints->n_points; j++) {
+ poly = Vect_point_in_poly(FPoints->x[0], FPoints->y[0], TPoints);
+ if (poly)
+ break;
+ }
+ }
+ if (poly) {
+ double tmp2_tx, tmp2_ty, tmp2_tz, tmp2_talong, tmp2_tangle;
+ double tmp2_fx, tmp2_fy, tmp2_fz, tmp2_falong, tmp2_fangle;
+ double tmp2_dist;
- if (j == 0 || tmp2_dist < tmp_dist) {
- tmp_dist = tmp2_dist;
- tmp_tx = tmp2_tx;
- tmp_ty = tmp2_ty;
+ /* 'from' area is inside 'to' area,
+ * get distance to 'to' isles */
+ nisles = Vect_get_area_num_isles(&To, tarea);
+ for (j = 0; j < nisles; j++) {
+ isle = Vect_get_area_isle(&To, tarea, j);
+ Vect_get_isle_points(&To, isle, TPoints);
+
+ line2area(&From, TPoints, ttype, area, &fbox,
+ &tmp2_tx, &tmp2_ty, &tmp2_tz, &tmp2_talong, &tmp2_tangle,
+ &tmp2_fx, &tmp2_fy, &tmp2_fz, &tmp2_falong, &tmp2_fangle,
+ &tmp2_dist, with_z, 0);
+
+ if (tmp2_dist < tmp_dist) {
+ tmp_dist = tmp2_dist;
+ tmp_fx = tmp2_fx;
+ tmp_fy = tmp2_fy;
+ tmp_fz = tmp2_fz;
+ tmp_falong = tmp2_falong;
+ tmp_fangle = tmp2_fangle;
+ tmp_tx = tmp2_tx;
+ tmp_ty = tmp2_ty;
+ tmp_tz = tmp2_tz;
+ tmp_talong = tmp2_talong;
+ tmp_tangle = tmp2_tangle;
+ }
}
}
}
- else { /* outside area */
- Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0],
- FPoints->z[0], WITHOUT_Z, &tmp_tx,
- &tmp_ty, NULL, &tmp_dist, NULL, NULL);
- }
if (tmp_dist > max || tmp_dist < min)
continue; /* not in threshold */
Vect_get_area_cats(&To, area, TCats);
@@ -872,41 +1055,51 @@
near->from_cat = fcat;
near->to_cat = tmp_tcat; /* -1 is OK */
near->dist = tmp_dist;
- near->from_x = FPoints->x[0];
- near->from_y = FPoints->y[0];
+ near->from_x = tmp_fx;
+ near->from_y = tmp_fy;
+ near->from_z = tmp_fz;
+ near->from_along = tmp_falong; /* 0 for points */
+ near->from_angle = tmp_fangle;
near->to_x = tmp_tx;
near->to_y = tmp_ty;
- near->to_along = 0; /* nonsense for areas */
- near->to_angle = 0; /* not supported for areas */
+ near->to_z = tmp_tz;
+ near->to_along = tmp_talong; /* 0 for points */
+ near->to_angle = tmp_tangle;
near->count++;
count++;
}
- else if (tarea == 0 || tmp_dist < dist) {
- tarea = area;
- tcat = tmp_tcat;
- dist = tmp_dist;
- tx = tmp_tx;
- ty = tmp_ty;
+ else {
+ if (tfeature == 0 || tmp_dist < dist) {
+ tfeature = tarea;
+ tcat = tmp_tcat;
+ dist = tmp_dist;
+ fx = tmp_fx;
+ fy = tmp_fy;
+ fz = tmp_fz;
+ falong = tmp_falong;
+ fangle = tmp_fangle;
+ tx = tmp_tx;
+ ty = tmp_ty;
+ tz = tmp_tz;
+ talong = tmp_talong;
+ tangle = tmp_tangle;
+ }
}
}
if (!do_all && curr_step < n_max_steps) {
/* enlarging the search box is possible */
- if (tarea > 0 && dist > box_edge) {
+ if (tfeature > 0 && dist > box_edge) {
/* area found but distance > search edge:
* area bbox overlaps with search box, area itself is outside search box */
done = FALSE;
}
- else if (tarea == 0) {
+ else if (tfeature == 0) {
/* no area within max dist, but search box can still be enlarged */
done = FALSE;
}
}
- if (done && !do_all && tarea > 0) {
- /* find near by cat */
- near =
- (NEAR *) bsearch((void *)&fcat, Near, nfcats,
- sizeof(NEAR), cmp_near);
+ if (done && !do_all && tfeature > 0) {
G_debug(4, "near.from_cat = %d near.count = %d dist = %f",
near->from_cat, near->count, near->dist);
@@ -915,12 +1108,16 @@
if (near->count == 0 || near->dist > dist) {
near->to_cat = tcat; /* -1 is OK */
near->dist = dist;
- near->from_x = FPoints->x[0];
- near->from_y = FPoints->y[0];
+ near->from_x = fx;
+ near->from_y = fy;
+ near->from_z = fz;
+ near->from_along = falong;
+ near->from_angle = fangle;
near->to_x = tx;
near->to_y = ty;
- near->to_along = 0; /* nonsense for areas */
- near->to_angle = 0; /* not supported for areas */
+ near->to_z = tz;
+ near->to_along = talong;
+ near->to_angle = tangle;
}
near->count++;
}
@@ -968,6 +1165,8 @@
}
}
+ update_ok = update_err = update_exist = update_notexist = update_dupl =
+ update_notfound = ncatexist = 0;
/* Update database / print to stdout / create output map */
if (flag.print->answer) { /* print header */
@@ -1028,8 +1227,6 @@
db_select_int(driver, Fi->table, Fi->key, NULL, &catexist);
G_debug(1, "%d cats selected from the table", ncatexist);
}
- update_ok = update_err = update_exist = update_notexist = update_dupl =
- update_notfound = 0;
if (!do_all) {
count = nfcats;
Modified: grass/trunk/vector/v.distance/v.distance.html
===================================================================
--- grass/trunk/vector/v.distance/v.distance.html 2012-10-13 11:56:04 UTC (rev 53386)
+++ grass/trunk/vector/v.distance/v.distance.html 2012-10-13 12:50:39 UTC (rev 53387)
@@ -1,24 +1,26 @@
<h2>DESCRIPTION</h2>
-<em>v.distance</em> finds the nearest element in vector map
-(<em>to</em>) for elements in vector map (<em>from</em>). Various
-information about the vectors' relationships (distance, category, etc.) may be uploaded
-to the attribute table attached to the first vector map, or printed to
-'stdout'. A new vector map may be created where lines connecting
-nearest points on features are written. <em>dmin</em> and/or <em>dmax</em> can be used to limit the search radius.
+<em>v.distance</em> finds the nearest element in vector map (<em>to</em>)
+for elements in vector map (<em>from</em>). Various information about
+the vectors' relationships (distance, category, etc.) may be uploaded to
+the attribute table attached to the first vector map, or printed to
+'stdout'. A new vector map may be created where lines connecting
+nearest points on features are written. <em>dmin</em> and/or
+<em>dmax</em> can be used to limit the search radius.
<h2>NOTES</h2>
-If a nearest feature does not have a category, the attribute column is updated
-to <em>null</em>. This is true also for areas, which means for example,
-that if a point is in an island (area WITHOUT category), <em>v.distance</em>
-does not search for the nearest area WITH category; the island is identified
-as the nearest and category updated to null.
-<p>The upload <em>column</em>(s) must already exist. Create one with <em>v.db.addcolumn</em>.
-<p>In lat-long locations <em>v.distance</em> gives distances (<em>dist</em>
-and <em>to_along</em>) in meters not in degrees calculated as geodesic
-distances on a sphere.
+If a nearest feature does not have a category, the attribute column is
+updated to <em>null</em>.
+<p>The upload <em>column</em>(s) must already exist. Create one with
+<em>v.db.addcolumn</em>.
+<!-- needs Vect_line_geodesic_distance()
+<p>In lat-long locations <em>v.distance</em> gives distances
+(<em>dist</em> and <em>to_along</em>) in meters not in degrees
+calculated as geodesic distances on a sphere.
+-->
+
<h2>EXAMPLES</h2>
<h3>Find nearest lines</h3>
@@ -37,7 +39,7 @@
For each point from vector map <b>pnt</b>, find the <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 an attribute table attached
-to vector map <b>pnt</b> (in the case that a point falls into a polygon area,
+to vector map <b>pnt</b> (in the case that a point falls into an area,
the distance is zero):
<div class="code"><pre>
@@ -143,6 +145,7 @@
Cmd line coordinates support: Markus Neteler, ITC-irst, Trento, Italy<br>
Updated for 5.1: Radim Blazek, ITC-irst, Trento, Italy<br>
Matrix-like output by Martin Landa, FBK-irst, Trento, Italy<br>
-Improved processing speed: Markus Metz
+Improved processing speed: Markus Metz<br>
+Distance from any feature to any feature Markus Metz
<p><i>Last changed: $Date$</i>
More information about the grass-commit
mailing list