vector3.h Atom Feed 0

In Brief This is a 3D vector class that can convert between different coordinate systems.
# 's
  1#ifndef VECTOR3_H
2#define VECTOR3_H
3
4// this class defines a 3D vector in different coordinate systems
5
6
7#include <cmath>
8#include <iostream>
9#include <assert>
10#include "angle.h"
11
12namespace Math {
13
14enum Coord3D {
15 X = 0,
16 Y,
17 Z
18};
19
20
21class Vector3
22{
23
24 private:
25 double data[3];
26
27 public:
28 Vector3()
29 {
30 data[X] = 0;
31 data[Y] = 0;
32 data[Z] = 0;
33 }
34
35 Vector3(double x, double y, double z)
36 {
37 data[X] = x;
38 data[Y] = y;
39 data[Z] = z;
40 }
41
42 /// accessors and setters
43 double& operator[] (unsigned index)
44 {
45 return data[index];
46 }
47
48 const double& operator[] (unsigned index) const
49 {
50 return data[index];
51 }
52
53 /// Cylindrical Coordinates
54 double radius() const
55 {
56 return sqrt(data[X] * data[X] + data[Y] * data[Y]);
57 }
58
59 Angle theta() const
60 {
61 return Angle(atan2(data[Y], data[X]));
62 }
63
64 // z is the same as Z
65 void cylindricalCoordinates(double& radius, Angle& theta,
66 double& z) const
67 {
68 radius = radius();
69 theta.setRadians(theta());
70 z = data[Z];
71 }
72
73 void cylindricalCoordinates(double& radius, double& theta,
74 double& z) const
75 {
76 radius = radius();
77 theta = theta();
78 z = data[Z];
79 }
80
81 // set the radius in cylindrical coordinates, theta and z stay constant
82 void setRadius(double radius)
83 {
84 double curRadius = radius();
85 if (0 == curRadius)
86 {
87 // we are going to project along the x-axis
88 data[X] = radius;
89 } else {
90 double scalar = radius / curRadius;
91 data[X] *= scalar;
92 data[Y] *= scalar;
93 }
94 }
95
96 // set theta in cylindrical coordinates, radius and Z stay the same
97 // set theta in spherical coordinates as well...
98 void setTheta(const Angle& theta)
99 {
100 double radius = radius();
101 data[X] = radius * cos(theta.radians());
102 data[Y] = radius * sin(theta.radians());
103 }
104
105 void setCylindricalCoordinates(double radius, const Angle& theta,
106 double z = 0)
107 {
108 data[X] = radius * cos(theta.radians());
109 data[Y] = radius * sin(theta.radians());
110 data[Z] = z;
111 }
112
113 /// Spherical Coordinates
114 // equations for theta should be the same
115 Angle phi() const
116 {
117 // TODO: I think this is correct, but it should be checked
118 return Angle(atan2(radius(), data[Z]));
119 }
120
121 // set phi without changing rho or theta
122 void setPhi(const Angle& phi)
123 {
124 // TODO: figure out how to do this...
125 }
126
127 double rho() const
128 {
129 return magnitude();
130 }
131
132 // set rho without changing theta or phi
133 void setRho(double rho)
134 {
135 double curRho = rho();
136 if (0 == curRho)
137 {
138 // we are just going to project rho along the x-axis
139 data[X] = rho;
140 } else {
141 *this *= rho / curRho;
142 }
143 }
144
145 void sphericalCoordinates(double& rho, Angle& theta, Angle& phi)
146 {
147 rho = rho();
148 theta = theta();
149 phi = phi();
150 }
151
152 void setSphericalCoordinates(double rho, const Angle& theta,
153 const Angle& phi)
154 {
155 // radius in cylindrical coordinates
156 double radius = rho * sin(phi.radians());
157 // solve for z
158 double z = rho * cos(phi.radians());
159 // use the cylindrical coordinate function
160 setCylindricalCoordinates(radius, theta, z);
161 }
162
163 /// operators
164 Vector3 operator - ()
165 {
166 return Vector3(-data[X], -data[Y], -data[Z]);
167 }
168
169 Vector3& operator = (const Vector3& rhs)
170 {
171 data[X] = rhs.data[X];
172 data[Y] = rhs.data[Y];
173 data[Z] = rhs.data[Z];
174 return *this;
175 }
176
177 Vector3& operator += (const Vector3& rhs)
178 {
179 data[X] += rhs.data[X];
180 data[Y] += rhs.data[Y];
181 data[Z] += rhs.data[Z];
182 return *this;
183 }
184
185 Vector3& operator -= (const Vector3& rhs)
186 {
187 data[X] -= rhs.data[X];
188 data[Y] -= rhs.data[Y];
189 data[Z] -= rhs.data[Z];
190 return *this;
191 }
192
193 Vector3& operator *= (const double rhs)
194 {
195 data[X] *= rhs;
196 data[Y] *= rhs;
197 data[Z] *= rhs;
198 return *this;
199 }
200
201 Vector3& operator /= (const double rhs)
202 {
203 data[X] /= rhs;
204 data[Y] /= rhs;
205 data[Z] /= rhs;
206 return *this;
207 }
208
209 double magnitudeSquared() const
210 {
211 return data[X]*data[X] + data[Y]*data[Y] + data[Z]*data[Z];
212 }
213
214 double magnitude() const
215 {
216 return std::sqrt(data[X]*data[X] + data[Y]*data[Y] + data[Z]*data[Z]);
217 }
218
219 Vector3& normalize()
220 {
221 double scale = magnitude();
222
223 // I cannot find any math resources online that say normalizing
224 // a zero-vector is well defined.
225 assert(scale != 0.0);
226
227 *this /= scale;
228
229 return *this;
230 }
231
232 Vector3& cross(const Vector3 &rhs)
233 {
234 data[X] = data[Y]*rhs[Z] - data[Z]*rhs[Y];
235 data[Y] = data[Z]*rhs[X] - data[X]*rhs[Z];
236 data[Z] = data[X]*rhs[Y] - data[Y]*rhs[X];
237 return *this;
238 }
239
240 private:
241// template <class Archive>
242// void serialize(Archive &ar, const unsigned int version)
243// {
244// ar & data[X];
245// ar & data[Y];
246// ar & data[Z];
247// }
248};
249
250inline std::ostream& operator << (std::ostream &os, const Vector3 &v)
251{
252 return os << '(' << v[X] << ", " << v[Y] << ", " << v[Z] << ')';
253}
254
255inline bool operator == (const Vector3 &lhs, const Vector3 &rhs)
256{
257 return lhs[X] == rhs[X]
258 && lhs[Y] == rhs[Y]
259 && lhs[Z] == rhs[Z];
260}
261
262inline bool operator != (const Vector3 &lhs, const Vector3 &rhs)
263{
264 return lhs[X] != rhs[X]
265 || lhs[Y] != rhs[Y]
266 || lhs[Z] != rhs[Z];
267}
268
269inline Vector3 operator + (const Vector3 &lhs, const Vector3 &rhs)
270{
271 Vector3 ret(lhs);
272 ret += rhs;
273 return ret;
274}
275
276inline Vector3 operator - (const Vector3 &lhs, const Vector3 &rhs)
277{
278 Vector3 ret(lhs);
279 ret -= rhs;
280 return ret;
281}
282
283inline Vector3 operator * (const Vector3 &lhs, const double rhs)
284{
285 Vector3 ret(lhs);
286 ret *= rhs;
287 return ret;
288}
289
290inline Vector3 operator * (const double lhs, const Vector3 &rhs)
291{
292 Vector3 ret(rhs);
293 ret *= lhs;
294 return ret;
295}
296
297inline Vector3 operator / (const Vector3 &lhs, const double rhs)
298{
299 Vector3 ret(lhs);
300 ret /= rhs;
301 return ret;
302}
303
304inline double abs(const Vector3 &orig)
305{
306 return orig.magnitude();
307}
308
309inline Vector3 normal(const Vector3 &orig)
310{
311 Vector3 ret(orig);
312 ret.normalize();
313 return ret;
314}
315
316inline double dot(const Vector3 &u, const Vector3 &v)
317{
318 return u[X]*v[X] + u[Y]*v[Y] + u[Z]*v[Z];
319}
320
321inline Vector3 cross(const Vector3 &u, const Vector3 &v)
322{
323 Vector3 ret;
324
325 ret[X] = u[Y]*v[Z] - u[Z]*v[Y];
326 ret[Y] = u[Z]*v[X] - u[X]*v[Z];
327 ret[Z] = u[X]*v[Y] - u[Y]*v[X];
328 return ret;
329}
330
331} // namespace Math
332
333// let's save some keystrokes
334using Math::Vector3;
335
336
337#endif

This is a 3D vector class that can convert between different coordinate systems.