The spica renderer
vector3d_detail.h
1 #ifdef _MSC_VER
2 #pragma once
3 #endif
4 
5 #ifndef _SPICA_VECTOR3D_DETAIL_H_
6 #define _SPICA_VECTOR3D_DETAIL_H_
7 
8 #include <iostream>
9 #include <iomanip>
10 #include <sstream>
11 #include <algorithm>
12 
13 namespace spica {
14 
15 template <class T>
17  : x_{ 0 }
18  , y_{ 0 }
19  , z_{ 0 } {
20 }
21 
22 template <class T>
23 Vector3_<T>::Vector3_(T x, T y, T z)
24  : x_{x}
25  , y_{y}
26  , z_{z} {
27 }
28 
29 template <class T>
30 Vector3_<T>::Vector3_(const std::string &str) {
31  double x, y, z;
32  if (sscanf(str.c_str(), "%lf %lf %lf", &x ,&y, &z) == 3 ||
33  sscanf(str.c_str(), "%lf, %lf, %lf", &x, &y, &z) == 3) {
34  this->x_ = x;
35  this->y_ = y;
36  this->z_ = z;
37  } else if (sscanf(str.c_str(), "%lf", &x) == 1) {
38  this->x_ = x;
39  this->y_ = x;
40  this->z_ = x;
41  } else {
42  FatalError("Cannot parse string \"%s\" for Vector3d", str.c_str());
43  }
44 }
45 
46 template <class T>
48  : x_{v.x_}
49  , y_{v.y_}
50  , z_{v.z_} {
51 }
52 
53 template <class T>
55 }
56 
57 template <class T>
60  this->x_ = v.x_;
61  this->y_ = v.y_;
62  this->z_ = v.z_;
63  return *this;
64 }
65 
66 template <class T>
67 Vector3_<T>&
68 Vector3_<T>::operator+=(const Vector3_<T>& v) {
69  this->x_ += v.x_;
70  this->y_ += v.y_;
71  this->z_ += v.z_;
72  return *this;
73 }
74 
75 template <class T>
76 Vector3_<T>&
77 Vector3_<T>::operator+=(double x) {
78  this->x_ += x;
79  this->y_ += x;
80  this->z_ += x;
81  return *this;
82 }
83 
84 template <class T>
85 Vector3_<T>&
86 Vector3_<T>::operator-=(const Vector3_<T>& v) {
87  this->operator+=(-v);
88  return *this;
89 }
90 
91 template <class T>
92 Vector3_<T>&
93 Vector3_<T>::operator-=(double x) {
94  this->operator+=(-x);
95  return *this;
96 }
97 
98 template <class T>
99 Vector3_<T>
100 Vector3_<T>::operator-() const {
101  return { -x_, -y_, -z_ };
102 }
103 
104 template <class T>
105 Vector3_<T>&
107  this->x_ *= v.x_;
108  this->y_ *= v.y_;
109  this->z_ *= v.z_;
110  return *this;
111 }
112 
113 template <class T>
115 Vector3_<T>::operator*=(double s) {
116  this->x_ *= s;
117  this->y_ *= s;
118  this->z_ *= s;
119  return *this;
120 }
121 
122 template <class T>
123 Vector3_<T>&
125  Assertion(v.x_ != 0 && v.y_ != 0 && v.z_ != 0, "Zero division");
126  this->x_ /= v.x_;
127  this->y_ /= v.y_;
128  this->z_ /= v.z_;
129  return *this;
130 }
131 
132 template <class T>
135  Assertion(s != 0.0, "Zero division");
136  return this->operator*=(1.0 / s);
137 }
138 
139 template <class T>
140 T Vector3_<T>::operator[](int i) const {
141  Assertion(i >= 0 && i <= 2, "Index out of bounds!!");
142  if (i == 0) return x_;
143  if (i == 1) return y_;
144  return z_;
145 }
146 
147 template <class T>
148 bool Vector3_<T>::operator==(const Vector3_<T>& v) const {
149  return (this->x_ == v.x_ && this->y_ == v.y_ && this->z_ == v.z_);
150 }
151 
152 template <class T>
153 bool Vector3_<T>::operator!=(const Vector3_<T>& v) const {
154  return !this->operator==(v);
155 }
156 
157 template <class T>
158 T Vector3_<T>::dot(const Vector3_<T>& v) const {
159  return this->x_ * v.x_ + this->y_ * v.y_ + this->z_ * v.z_;
160 }
161 
162 template <class T>
163 T Vector3_<T>::dot(const Vector3_<T>& v1,
164  const Vector3_<T>& v2) {
165  return v1.dot(v2);
166 }
167 
168 template <class T>
169 Vector3_<T>
170 Vector3_<T>::cross(const Vector3_<T>& v) const {
171  T x = this->y_ * v.z_ - this->z_ * v.y_;
172  T y = this->z_ * v.x_ - this->x_ * v.z_;
173  T z = this->x_ * v.y_ - this->y_ * v.x_;
174  return { x, y, z };
175 }
176 
177 template <class T>
178 Vector3_<T>
179 Vector3_<T>::cross(const Vector3_<T>& v1,
180  const Vector3_<T>& v2) {
181  return v1.cross(v2);
182 }
183 
184 template <class T>
185 double Vector3_<T>::norm() const {
186  return ::sqrt(this->squaredNorm());
187 }
188 
189 template <class T>
190 double Vector3_<T>::squaredNorm() const {
191  return this->dot(*this);
192 }
193 
194 template <class T>
195 Vector3_<T>
196 Vector3_<T>::normalized() const {
197  Vector3_<T> ret = *this;
198  ret /= ret.norm();
199  return ret;
200 }
201 
202 template <class T>
203 Vector3_<T>
204 Vector3_<T>::normalize(const Vector3_<T>& v) {
205  return v.normalized();
206 }
207 
208 template <class T>
209 Vector3_<T>
210 Vector3_<T>::multiply(const Vector3_<T>& v) const {
211  return (*this) * v;
212 }
213 
214 template <class T>
215 Vector3_<T>
216 Vector3_<T>::minimum(const Vector3_<T>& v1,
217  const Vector3_<T>& v2) {
218  T x = std::min(v1.x_, v2.x_);
219  T y = std::min(v1.y_, v2.y_);
220  T z = std::min(v1.z_, v2.z_);
221  return { x, y, z };
222 }
223 
224 template <class T>
225 Vector3_<T>
226 Vector3_<T>::maximum(const Vector3_<T>& v1,
227  const Vector3_<T>& v2) {
228  T x = std::max(v1.x(), v2.x());
229  T y = std::max(v1.y(), v2.y());
230  T z = std::max(v1.z(), v2.z());
231  return { x, y, z };
232 }
233 
234 template <class T>
235 T Vector3_<T>::get(int d) const {
236  Assertion(0 <= d && d <= 2, "Dimension must be between 0 and 2");
237  if (d == 0) return x_;
238  if (d == 1) return y_;
239  if (d == 2) return z_;
240  return 0.0;
241 }
242 
243 template <class T>
244 std::string Vector3_<T>::toString() const {
245  std::stringstream ss;
246  ss << std::fixed;
247  ss << std::setprecision(8);
248  ss << "(" << x_ << ", " << y_ << ", " << z_ << ")";
249  return std::move(ss.str());
250 }
251 
252 } // namespace spica
253 
254 template <class T>
256 operator+(const spica::Vector3_<T>& v1,
257  const spica::Vector3_<T>& v2) {
258  spica::Vector3_<T> ret = v1;
259  ret += v2;
260  return ret;
261 }
262 
263 template <class T>
265 operator-(const spica::Vector3_<T>& v1,
266  const spica::Vector3_<T>& v2) {
267  spica::Vector3_<T> ret = v1;
268  ret -= v2;
269  return ret;
270 }
271 
272 template <class T>
274 operator+(const spica::Vector3_<T>& v, T x) {
275  spica::Vector3_<T> ret = v;
276  ret += x;
277  return ret;
278 }
279 
280 template <class T>
282 operator+(T x, const spica::Vector3_<T>& v) {
283  return v + x;
284 }
285 
286 template <class T>
288 operator-(const spica::Vector3_<T>& v, T x) {
289  return v + (-x);
290 }
291 
292 template <class T>
294 operator-(T x, const spica::Vector3_<T>& v) {
295  return x + (-v);
296 }
297 
298 template <class T>
300 operator*(const spica::Vector3_<T>& u,
301  const spica::Vector3_<T>& v) {
302  spica::Vector3_<T> ret = u;
303  ret *= v;
304  return ret;
305 }
306 
307 template <class T>
309 operator*(const spica::Vector3_<T>& v, double s) {
310  spica::Vector3_<T> ret = v;
311  ret *= s;
312  return ret;
313 }
314 
315 template <class T>
317 operator*(double s, const spica::Vector3_<T>& v) {
318  spica::Vector3_<T> ret = v;
319  ret *= s;
320  return ret;
321 }
322 
323 template <class T>
325 operator/(const spica::Vector3_<T>& u,
326  const spica::Vector3_<T>& v) {
327  spica::Vector3_<T> ret = u;
328  ret /= v;
329  return ret;
330 }
331 
332 template <class T>
334 operator/(const spica::Vector3_<T>& v, double s) {
335  spica::Vector3_<T> ret = v;
336  ret /= s;
337  return ret;
338 }
339 
340 template <class T>
341 std::ostream& operator<<(std::ostream& os,
342  const spica::Vector3_<T>& v) {
343  os << v.toString();
344  return os;
345 }
346 
347 #endif // _SPICA_VECTOR3D_DETAIL_H_
Vector3_()
The Vector3d constructor.
Definition: vector3d_detail.h:16
Three-dimensional vector.
Definition: core.hpp:56
Vector3_ & operator/=(const Vector3_ &v)
Element-wise division.
Definition: vector3d_detail.h:124
virtual ~Vector3_()
The Vector3d destructor.
Definition: vector3d_detail.h:54
Vector3_ & operator*=(const Vector3_ &v)
Element-wise multiplication.
Definition: vector3d_detail.h:106