123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- /*!
- \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 <landa.martin gmail.com> (May 2008)
- */
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/ogsf.h>
- /*!
- \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);
- }
|