GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/ell/vecEll.c Lines: 14 67 20.9 %
Date: 2017-05-26 Branches: 10 26 38.5 %

Line Branch Exec Source
1
/*
2
  Teem: Tools to process and visualize scientific data and images             .
3
  Copyright (C) 2013, 2012, 2011, 2010, 2009  University of Chicago
4
  Copyright (C) 2008, 2007, 2006, 2005  Gordon Kindlmann
5
  Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998  University of Utah
6
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public License
9
  (LGPL) as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
  The terms of redistributing and/or modifying this software also
12
  include exceptions to the LGPL that facilitate static linking.
13
14
  This library is distributed in the hope that it will be useful,
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
  Lesser General Public License for more details.
18
19
  You should have received a copy of the GNU Lesser General Public License
20
  along with this library; if not, write to Free Software Foundation, Inc.,
21
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
*/
23
24
25
#include "ell.h"
26
27
void
28
ell_4v_norm_f(float bv[4], const float av[4]) {
29
  float len;
30
31
  len = AIR_CAST(float, ELL_4V_LEN(av));
32
  ELL_4V_SCALE(bv, 1.0f/len, av);
33
  return;
34
}
35
36
#define PERP \
37
  idx = 0; \
38
  if (b[0]*b[0] < b[1]*b[1]) \
39
    idx = 1; \
40
  if (b[idx]*b[idx] < b[2]*b[2]) \
41
    idx = 2; \
42
  switch (idx) { \
43
  case 0: \
44
    ELL_3V_SET(a, b[1] - b[2], -b[0], b[0]); \
45
    break; \
46
  case 1: \
47
    ELL_3V_SET(a, -b[1], b[0] - b[2], b[1]); \
48
    break; \
49
  case 2: \
50
    ELL_3V_SET(a, -b[2], b[2], b[0] - b[1]); \
51
    break; \
52
  }
53
54
/*
55
******** ell_3v_perp_f()
56
**
57
** Given a 3-vector, produce one which is perpendicular.
58
** Output length won't be same as input length, but it will always
59
** be non-zero, if input length is non-zero.   This does NOT try to
60
** produce a unit-length vector, regardless of the length of the input.
61
*/
62
void
63
ell_3v_perp_f(float a[3], const float b[3]) {
64
  int idx;
65
  PERP;
66
}
67
68
/*
69
******** ell_3v_perp_d()
70
**
71
** same as above, but for doubles
72
*/
73
void
74
ell_3v_perp_d(double a[3], const double b[3]) {
75
  int idx;
76


552
  PERP;
77
80
}
78
79
void
80
ell_3mv_mul_f(float v2[3], const float m[9], const float v1[3]) {
81
  float tmp[3];
82
83
  ELL_3MV_MUL(tmp, m, v1);
84
  ELL_3V_COPY(v2, tmp);
85
}
86
87
void
88
ell_3mv_mul_d(double v2[3], const double m[9], const double v1[3]) {
89
  double tmp[3];
90
91
2099810
  ELL_3MV_MUL(tmp, m, v1);
92
1049905
  ELL_3V_COPY(v2, tmp);
93
1049905
}
94
95
void
96
ell_4mv_mul_f(float v2[4], const float m[16], const float v1[4]) {
97
  float tmp[4];
98
99
  ELL_4MV_MUL(tmp, m, v1);
100
  ELL_4V_COPY(v2, tmp);
101
}
102
103
void
104
ell_4mv_mul_d(double v2[4], const double m[16], const double v1[4]) {
105
  double tmp[4];
106
107
  ELL_4MV_MUL(tmp, m, v1);
108
  ELL_4V_COPY(v2, tmp);
109
}
110
111
/*
112
** hat tip to http://www.plunk.org/~hatch/rightway.php
113
*/
114
float
115
ell_3v_angle_f(const float _uu[3], const float _vv[3]) {
116
  float tmp[3], len, uu[3], vv[3], ret;
117
118
  ELL_3V_NORM_TT(uu, float, _uu, len);
119
  ELL_3V_NORM_TT(vv, float, _vv, len);
120
  if (ELL_3V_DOT(uu, vv) < 0.0) {
121
    ELL_3V_ADD2(tmp, uu, vv);
122
    ret = AIR_CAST(float, AIR_PI - 2*asin(ELL_3V_LEN(tmp)/2.0));
123
  } else {
124
    ELL_3V_SUB(tmp, uu, vv);
125
    ret = AIR_CAST(float, 2*asin(ELL_3V_LEN(tmp)/2.0));
126
  }
127
  return ret;
128
}
129
130
/* HEY: copy and paste */
131
double
132
ell_3v_angle_d(const double _uu[3], const double _vv[3]) {
133
  double tmp[3], len, uu[3], vv[3], ret;
134
135
345144
  ELL_3V_NORM(uu, _uu, len);
136
172572
  ELL_3V_NORM(vv, _vv, len);
137
172572
  if (ELL_3V_DOT(uu, vv) < 0.0) {
138
78978
    ELL_3V_ADD2(tmp, uu, vv);
139
78978
    ret = AIR_PI - 2*asin(ELL_3V_LEN(tmp)/2.0);
140
78978
  } else {
141
93594
    ELL_3V_SUB(tmp, uu, vv);
142
93594
    ret = 2*asin(ELL_3V_LEN(tmp)/2.0);
143
  }
144
172572
  return ret;
145
}
146
147
/* HEY: copy and paste */
148
float
149
ell_2v_angle_f(const float _uu[2], const float _vv[2]) {
150
  float tmp[2], len, uu[2], vv[2], ret;
151
152
  ELL_2V_NORM_TT(uu, float, _uu, len);
153
  ELL_2V_NORM_TT(vv, float, _vv, len);
154
  if (ELL_2V_DOT(uu, vv) < 0.0) {
155
    ELL_2V_ADD2(tmp, uu, vv);
156
    ret = AIR_CAST(float, AIR_PI - 2*asin(ELL_2V_LEN(tmp)/2.0));
157
  } else {
158
    ELL_2V_SUB(tmp, uu, vv);
159
    ret = AIR_CAST(float, 2*asin(ELL_2V_LEN(tmp)/2.0));
160
  }
161
  return ret;
162
}
163
164
/* HEY: copy and paste */
165
double
166
ell_2v_angle_d(const double _uu[2], const double _vv[2]) {
167
  double tmp[2], len, uu[2], vv[2], ret;
168
169
  ELL_2V_NORM(uu, _uu, len);
170
  ELL_2V_NORM(vv, _vv, len);
171
  if (ELL_2V_DOT(uu, vv) < 0.0) {
172
    ELL_2V_ADD2(tmp, uu, vv);
173
    ret = AIR_PI - 2*asin(ELL_2V_LEN(tmp)/2.0);
174
  } else {
175
    ELL_2V_SUB(tmp, uu, vv);
176
    ret = 2*asin(ELL_2V_LEN(tmp)/2.0);
177
  }
178
  return ret;
179
}
180
181
/*
182
** input vectors have to be normalized!
183
*/
184
double
185
ell_3v_area_spherical_d(const double avec[3],
186
                        const double bvec[3],
187
                        const double cvec[3]) {
188
  double axb[3], bxc[3], cxa[3], A, B, C, tmp;
189
190
  ELL_3V_CROSS(axb, avec, bvec);
191
  ELL_3V_CROSS(bxc, bvec, cvec);
192
  ELL_3V_CROSS(cxa, cvec, avec);
193
  ELL_3V_NORM(axb, axb, tmp);
194
  ELL_3V_NORM(bxc, bxc, tmp);
195
  ELL_3V_NORM(cxa, cxa, tmp);
196
  A = AIR_PI - ell_3v_angle_d(axb, cxa);
197
  B = AIR_PI - ell_3v_angle_d(bxc, axb);
198
  C = AIR_PI - ell_3v_angle_d(cxa, bxc);
199
  return A + B + C - AIR_PI;
200
}
201
202
/*
203
** all input vectors {a,b,c}vec, dir must be normalized
204
*/
205
void
206
ell_3v_barycentric_spherical_d(double bary[3],
207
                               const double av[3],
208
                               const double bv[3],
209
                               const double cv[3],
210
                               const double vv[3]) {
211
  double sum;
212
213
  bary[0] = ell_3v_area_spherical_d(vv, bv, cv);
214
  bary[1] = ell_3v_area_spherical_d(vv, cv, av);
215
  bary[2] = ell_3v_area_spherical_d(vv, av, bv);
216
  sum = bary[0] + bary[1] + bary[2];
217
  if (sum) {
218
    ELL_3V_SCALE(bary, 1.0/sum, bary);
219
  }
220
  return;
221
}