[GRASS-SVN] r61978 - grass/trunk/lib/vector/Vlib
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Sep 15 11:27:01 PDT 2014
Author: mmetz
Date: 2014-09-15 11:27:01 -0700 (Mon, 15 Sep 2014)
New Revision: 61978
Modified:
grass/trunk/lib/vector/Vlib/line.c
Log:
Vlib: add Vect_line_geodesic_distance()
Modified: grass/trunk/lib/vector/Vlib/line.c
===================================================================
--- grass/trunk/lib/vector/Vlib/line.c 2014-09-15 15:17:57 UTC (rev 61977)
+++ grass/trunk/lib/vector/Vlib/line.c 2014-09-15 18:27:01 UTC (rev 61978)
@@ -630,7 +630,7 @@
}
/*!
- \brief Calculate line distance.
+ \brief Calculate distance of point to line.
Sets (if not null):
- px, py - point on line,
@@ -750,7 +750,141 @@
return (segment);
}
+/*!
+ \brief Calculate geodesic distance of point to line in meters.
+
+ Sets (if not null):
+ - px, py - point on line,
+ - dist - distance to line,
+ - spdist - distance to point on line from segment beginning,
+ - sldist - distance to point on line form line beginning along line
+ \param points pointer to line_pnts structure
+ \param ux,uy,uz point coordinates
+ \param with_z flag if to use z coordinate (3D calculation)
+ \param[out] px,py,pz point on line
+ \param[out] dist distance to line,
+ \param[out] spdist distance of point from segment beginning
+ \param[out] lpdist distance of point from line
+
+ \return nearest segment (first is 1)
+ */
+int Vect_line_geodesic_distance(const struct line_pnts *points,
+ double ux, double uy, double uz,
+ int with_z,
+ double *px, double *py, double *pz,
+ double *dist, double *spdist,
+ double *lpdist)
+{
+ int i;
+ double distance;
+ double new_dist;
+ double tpx, tpy, tpz, ttpx, ttpy, ttpz;
+ double tdist, tspdist, tlpdist = 0, tlpdistseg;
+ double dz;
+ int n_points;
+ int segment;
+
+ G_begin_distance_calculations();
+
+ n_points = points->n_points;
+
+ if (n_points == 1) {
+ distance = G_distance(ux, uy, points->x[0], points->y[0]);
+ if (with_z)
+ distance = hypot(distance, uz - points->z[0]);
+
+ tpx = points->x[0];
+ tpy = points->y[0];
+ tpz = points->z[0];
+ tdist = distance;
+ tspdist = 0;
+ tlpdist = 0;
+ segment = 0;
+
+ }
+ else {
+
+ distance =
+ dig_distance2_point_to_line(ux, uy, uz, points->x[0],
+ points->y[0], points->z[0],
+ points->x[1], points->y[1],
+ points->z[1], with_z,
+ &tpx, &tpy, &tpz,
+ NULL, NULL);
+
+ distance = G_distance(ux, uy, tpx, tpy);
+ if (with_z)
+ distance = hypot(distance, uz - tpz);
+
+ segment = 1;
+
+ for (i = 1; i < n_points - 1; i++) {
+ new_dist = dig_distance2_point_to_line(ux, uy, uz,
+ points->x[i], points->y[i],
+ points->z[i],
+ points->x[i + 1],
+ points->y[i + 1],
+ points->z[i + 1], with_z,
+ &ttpx, &ttpy, &ttpz,
+ NULL, NULL);
+ new_dist = G_distance(ux, uy, ttpx, ttpy);
+ if (with_z)
+ new_dist = hypot(new_dist, uz - ttpz);
+
+ if (new_dist < distance) {
+ distance = new_dist;
+ segment = i + 1;
+ tpx = ttpx;
+ tpy = ttpy;
+ tpz = ttpz;
+ }
+ }
+
+ /* calculate distance from beginning of segment */
+ tspdist = G_distance(points->x[segment - 1], points->y[segment - 1],
+ tpx, tpy);
+ if (with_z) {
+ dz = points->z[segment - 1] - tpz;
+ tspdist += hypot(tspdist, dz);
+ }
+
+ /* calculate distance from beginning of line */
+ if (lpdist) {
+ tlpdist = 0;
+ for (i = 0; i < segment - 1; i++) {
+ tlpdistseg = G_distance(points->x[i], points->y[i],
+ points->x[i + 1], points->y[i + 1]);
+
+ if (with_z) {
+ dz = points->z[i + 1] - points->z[i];
+ tlpdistseg += hypot(tlpdistseg, dz);
+ }
+
+ tlpdist += tlpdistseg;
+ }
+ tlpdist += tspdist;
+ }
+ tdist = distance;
+ }
+
+ if (px)
+ *px = tpx;
+ if (py)
+ *py = tpy;
+ if (pz && with_z)
+ *pz = tpz;
+ if (dist)
+ *dist = tdist;
+ if (spdist)
+ *spdist = tspdist;
+ if (lpdist)
+ *lpdist = tlpdist;
+
+ return (segment);
+}
+
+
/*!
\brief Calculate distance of 2 points
More information about the grass-commit
mailing list