Loading...
Searching...
No Matches
gs_util.c
Go to the documentation of this file.
/*!
\file lib/ogsf/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[in] from starting point (X,Y)
\param[in] to ending point (X,Y)
\param[in] 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[in] from 'from' point (X,Y,Z)
\param[in] 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[in] from 'from' point (X,Y)
\param[in] 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 3D vector (X,Y,Z)
\param[in] v2 second 3D vector (X,Y,Z)
*/
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 3D vector (X,Y,Z)
\param[in] v2 second 3D vector (X,Y,Z)
*/
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 3D vector (X,Y,Z)
\param v2 second 3D vector (X,Y,Z)
*/
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 3D vector (X,Y,Z)
\param[in] 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 (3D)
\param[in,out] v1 3D vector (X,Y,Z)
\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 (2D)
\param[in,out] v1 2D vector (X,Y)
\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[in,out] dv1 3D vector (X,Y,Z)
\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[in] v1 first 3D vector (X,Y,Z)
\param[in,out] v2 second 3D vector (X,Y,Z)
\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[in] v1 first 3D vector (X,Y,Z)
\param[in] v2 second 3D vector (X,Y,Z)
\param[out] v3 output 3D vector (X,Y,Z)
\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[in] v1 first 2D vector (X,Y)
\param[in] v2 second 2D vector (X,Y)
\param[out] v3 output 2D vector (X,Y)
\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[in] v1 first 3D vector (X,Y,Z)
\param[in] v2 second 3D vector (X,Y,Z)
\param[out] v3 output 3D vector (X,Y,Z)
*/
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[in] v1 3D vector (X,Y,Z)
\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 entries to check, then call with zero as nhist
\param[in] p1 first point
\param[in] p2 second point
\param[in] 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);
}
G_free
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:147
NULL
#define NULL
Definition ccmath.h:32
Gs_distance
double Gs_distance(double *from, double *to)
Calculates distance in METERS between two points in current projection (2D).
Definition gs3.c:79
GS_v2dir
void GS_v2dir(float *v1, float *v2, float *v3)
Get a normalized direction from v1 to v2, store in v3 (2D).
Definition gs_util.c:382
GS_v3sub
void GS_v3sub(float *v1, float *v2)
Subtract vectors.
Definition gs_util.c:212
GS_v3mult
void GS_v3mult(float *v1, float k)
Multiple vectors.
Definition gs_util.c:229
GS_v3mag
void GS_v3mag(float *v1, float *mag)
Magnitude of vector.
Definition gs_util.c:418
GS_dv3norm
int GS_dv3norm(double *dv1)
Changes v1 so that it is a unit vector.
Definition gs_util.c:295
GS_coordpair_repeats
int GS_coordpair_repeats(float *p1, float *p2, int nhist)
ADD.
Definition gs_util.c:440
GS_distance
float GS_distance(float *from, float *to)
Calculate distance.
Definition gs_util.c:141
GS_v2norm
int GS_v2norm(float *v1)
Change v1 so that it is a unit vector (2D).
Definition gs_util.c:271
GS_v3add
void GS_v3add(float *v1, float *v2)
Sum vectors.
Definition gs_util.c:195
GS_v3norm
int GS_v3norm(float *v1)
Change v1 so that it is a unit vector (3D).
Definition gs_util.c:246
GS_v3eq
void GS_v3eq(float *v1, float *v2)
Copy vector values.
Definition gs_util.c:178
GS_geodistance
double GS_geodistance(double *from, double *to, const char *units)
Calculate distance between 2 coordinates.
Definition gs_util.c:55
GS_P2distance
float GS_P2distance(float *from, float *to)
Calculate distance in plane.
Definition gs_util.c:160
GS_v3dir
int GS_v3dir(float *v1, float *v2, float *v3)
Get a normalized direction from v1 to v2, store in v3.
Definition gs_util.c:351
GS_v3normalize
int GS_v3normalize(float *v1, float *v2)
Change v2 so that v1v2 is a unit vector.
Definition gs_util.c:321
GS_v3cross
void GS_v3cross(float *v1, float *v2, float *v3)
Get the cross product v3 = v1 cross v2.
Definition gs_util.c:403
X
#define X(j)
x
#define x
Y
#define Y(j)