/*! \file GS_util.c \brief OGSF library - loading and manipulating surfaces GRASS OpenGL gsurf OGSF Library (C) 1999-2008 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. \author Bill Brown USACERL, GMSL/University of Illinois \author Doxygenized by Martin Landa (May 2008) */ #include #include #include #include #include /*! \brief Calculate distance between 2 coordinates Units is one of: - "meters", - "miles", - "kilometers", - "feet", - "yards", - "nmiles" (nautical miles), - "rods", - "inches", - "centimeters", - "millimeters", - "micron", - "nanometers", - "cubits", - "hands", - "furlongs", - "chains" Default is meters. \param from starting point \param to ending point \param units map units \return distance between two geographic coordinates in current projection */ double GS_geodistance(double *from, double *to, const char *units) { double meters; meters = Gs_distance(from, to); if (!units) { return (meters); } if (strcmp(units, "meters") == 0) { return (meters); } if (strcmp(units, "miles") == 0) { return (meters * .0006213712); } if (strcmp(units, "kilometers") == 0) { return (meters * .001); } if (strcmp(units, "feet") == 0) { return (meters * 3.280840); } if (strcmp(units, "yards") == 0) { return (meters * 1.093613); } if (strcmp(units, "rods") == 0) { return (meters * .1988388); } if (strcmp(units, "inches") == 0) { return (meters * 39.37008); } if (strcmp(units, "centimeters") == 0) { return (meters * 100.0); } if (strcmp(units, "millimeters") == 0) { return (meters * 1000.0); } if (strcmp(units, "micron") == 0) { return (meters * 1000000.0); } if (strcmp(units, "nanometers") == 0) { return (meters * 1000000000.0); } if (strcmp(units, "cubits") == 0) { return (meters * 2.187227); } if (strcmp(units, "hands") == 0) { return (meters * 9.842520); } if (strcmp(units, "furlongs") == 0) { return (meters * .004970970); } if (strcmp(units, "nmiles") == 0) { /* nautical miles */ return (meters * .0005399568); } if (strcmp(units, "chains") == 0) { return (meters * .0497097); } return (meters); } /*! \brief Calculate distance \param from 'from' point (X,Y,Z) \param to 'to' point (X,Y,Z) \return distance */ float GS_distance(float *from, float *to) { float x, y, z; x = from[X] - to[X]; y = from[Y] - to[Y]; z = from[Z] - to[Z]; return (float)sqrt(x * x + y * y + z * z); } /*! \brief Calculate distance in plane \param from 'from' point (X,Y) \param to 'to' point (X,Y) \return distance */ float GS_P2distance(float *from, float *to) { float x, y; x = from[X] - to[X]; y = from[Y] - to[Y]; return (float)sqrt(x * x + y * y); } /*! \brief Copy vector values v1 = v2 \param[out] v1 first vector \param v2 second vector */ void GS_v3eq(float *v1, float *v2) { v1[X] = v2[X]; v1[Y] = v2[Y]; v1[Z] = v2[Z]; return; } /*! \brief Sum vectors v1 += v2 \param[in,out] v1 first vector \param v2 second vector */ void GS_v3add(float *v1, float *v2) { v1[X] += v2[X]; v1[Y] += v2[Y]; v1[Z] += v2[Z]; return; } /*! \brief Subtract vectors v1 -= v2 \param[in,out] v1 first vector \param v2 second vector */ void GS_v3sub(float *v1, float *v2) { v1[X] -= v2[X]; v1[Y] -= v2[Y]; v1[Z] -= v2[Z]; return; } /*! \brief Multiple vectors v1 *= k \param[in,out] v1 vector \param k multiplicator */ void GS_v3mult(float *v1, float k) { v1[X] *= k; v1[Y] *= k; v1[Z] *= k; return; } /*! \brief Change v1 so that it is a unit vector (2D) \param[in,out] v1 vector \return 0 if magnitude of v1 is zero \return 1 if magnitude of v1 > 0 */ int GS_v3norm(float *v1) { float n; n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]); if (n == 0.0) { return (0); } v1[X] /= n; v1[Y] /= n; v1[Z] /= n; return (1); } /*! \brief Change v1 so that it is a unit vector (3D) \param[in,out] v1 vector \return 0 if magnitude of v1 is zero \return 1 if magnitude of v1 > 0 */ int GS_v2norm(float *v1) { float n; n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y]); if (n == 0.0) { return (0); } v1[X] /= n; v1[Y] /= n; return (1); } /*! \brief Changes v1 so that it is a unit vector \param dv1 vector \return 0 if magnitude of dv1 is zero \return 1 if magnitude of dv1 > 0 */ int GS_dv3norm(double *dv1) { double n; n = sqrt(dv1[X] * dv1[X] + dv1[Y] * dv1[Y] + dv1[Z] * dv1[Z]); if (n == 0.0) { return (0); } dv1[X] /= n; dv1[Y] /= n; dv1[Z] /= n; return (1); } /*! \brief Change v2 so that v1v2 is a unit vector \param v1 first vector \param v2[in,out] second vector \return 0 if magnitude of dx is zero \return 1 if magnitude of dx > 0 */ int GS_v3normalize(float *v1, float *v2) { float n, dx, dy, dz; dx = v2[X] - v1[X]; dy = v2[Y] - v1[Y]; dz = v2[Z] - v1[Z]; n = sqrt(dx * dx + dy * dy + dz * dz); if (n == 0.0) { return (0); } v2[X] = v1[X] + dx / n; v2[Y] = v1[Y] + dy / n; v2[Z] = v1[Z] + dz / n; return (1); } /*! \brief Get a normalized direction from v1 to v2, store in v3 \param v1 first vector \param v2 second vector \param[out] v3 output vector \return 0 if magnitude of dx is zero \return 1 if magnitude of dx > 0 */ int GS_v3dir(float *v1, float *v2, float *v3) { float n, dx, dy, dz; dx = v2[X] - v1[X]; dy = v2[Y] - v1[Y]; dz = v2[Z] - v1[Z]; n = sqrt(dx * dx + dy * dy + dz * dz); if (n == 0.0) { v3[X] = v3[Y] = v3[Z] = 0.0; return (0); } v3[X] = dx / n; v3[Y] = dy / n; v3[Z] = dz / n; return (1); } /*! \brief Get a normalized direction from v1 to v2, store in v3 (2D) \param v1 first vector \param v2 second vector \param[out] v3 output vector \return 0 if magnitude of dx is zero \return 1 if magnitude of dx > 0 */ void GS_v2dir(float *v1, float *v2, float *v3) { float n, dx, dy; dx = v2[X] - v1[X]; dy = v2[Y] - v1[Y]; n = sqrt(dx * dx + dy * dy); v3[X] = dx / n; v3[Y] = dy / n; return; } /*! \brief Get the cross product v3 = v1 cross v2 \param v1 first vector \param v2 second vector \param[out] v3 output vector */ void GS_v3cross(float *v1, float *v2, float *v3) { v3[X] = (v1[Y] * v2[Z]) - (v1[Z] * v2[Y]); v3[Y] = (v1[Z] * v2[X]) - (v1[X] * v2[Z]); v3[Z] = (v1[X] * v2[Y]) - (v1[Y] * v2[X]); return; } /*! \brief Magnitude of vector \param v1 vector \param[out] mag magnitude value */ void GS_v3mag(float *v1, float *mag) { *mag = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]); return; } /*! \brief ADD Initialize by calling with a number nhist to represent number of previous entrys to check, then call with zero as nhist \param p1 first point \param p2 second point \param nhist ? \return -1 on error \return -2 \return 1 \return 9 */ int GS_coordpair_repeats(float *p1, float *p2, int nhist) { static float *entrys = NULL; static int next = 0; static int len = 0; int i; if (nhist) { if (entrys) { G_free(entrys); } entrys = (float *)G_malloc(4 * nhist * sizeof(float)); if (!entrys) return (-1); len = nhist; next = 0; } if (!len) { return (-2); } for (i = 0; i < next; i += 4) { if (entrys[i] == p1[0] && entrys[i + 1] == p1[1] && entrys[i + 2] == p2[0] && entrys[i + 3] == p2[1]) { return (1); } } if (len == next / 4) { next = 0; } entrys[next] = p1[0]; entrys[next + 1] = p1[1]; entrys[next + 2] = p2[0]; entrys[next + 3] = p2[1]; next += 4; return (0); }