STIR 6.4.0
BasicCoordinate.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2000 PARAPET partners
5 Copyright (C) 2000 - 2007-10-08, Hammersmith Imanet Ltd
6 Copyright (C) 2011-07-01 - 2012, Kris Thielemans
7 This file is part of STIR.
8
9 SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
10
11 See STIR/LICENSE.txt for details
12*/
24
26// for std::inner_product
27#include <numeric>
28// for sqrt and acos
29#include <cmath>
30// for equal and fill
31#include <algorithm>
32#include <stdexcept>
33
34START_NAMESPACE_STIR
35
36/*
37 iterators
38*/
39template <int num_dimensions, class coordT>
40typename BasicCoordinate<num_dimensions, coordT>::iterator
41BasicCoordinate<num_dimensions, coordT>::begin()
42{
43 return coords;
44}
45
46template <int num_dimensions, class coordT>
47typename BasicCoordinate<num_dimensions, coordT>::const_iterator
48BasicCoordinate<num_dimensions, coordT>::begin() const
49{
50 return coords;
51}
52
53template <int num_dimensions, class coordT>
54typename BasicCoordinate<num_dimensions, coordT>::iterator
55BasicCoordinate<num_dimensions, coordT>::end()
56{
57 return coords + num_dimensions;
58}
59
60template <int num_dimensions, class coordT>
61typename BasicCoordinate<num_dimensions, coordT>::const_iterator
62BasicCoordinate<num_dimensions, coordT>::end() const
63{
64 return coords + num_dimensions;
65}
66
67/*
68 operator[] and at
69*/
70template <int num_dimensions, class coordT>
71coordT&
73{
74 assert(d > 0);
75 assert(d <= num_dimensions);
76 return coords[d - 1];
77}
78
79template <int num_dimensions, class coordT>
80coordT const&
82{
83 assert(d > 0);
84 assert(d <= num_dimensions);
85 return coords[d - 1];
86}
87
88template <int num_dimensions, class coordT>
89coordT&
91{
92 if (d <= 0 || d > num_dimensions)
93 throw std::out_of_range("index out of range");
94 return coords[d - 1];
95}
96
97template <int num_dimensions, class coordT>
98coordT const&
101 if (d <= 0 || d > num_dimensions)
102 throw std::out_of_range("index out of range");
103 return coords[d - 1];
104}
105
107 comparison
108 */
109template <int num_dimensions, class coordT>
110bool
112{
113 return std::equal(begin(), end(), c.begin());
114}
115
116/*
117 assignments and onstructors
119template <int num_dimensions, class coordT>
122{
123 for (int i = 1; i <= num_dimensions; i++)
124 (*this)[i] = c[i];
125 return *this;
126}
127
128template <int num_dimensions, class coordT>
129void
131{
132 std::fill(this->begin(), this->end(), c);
133}
134
135template <int num_dimensions, class coordT>
139template <int num_dimensions, class coordT>
141{
142 this->fill(c);
143}
144
145#if 0
146template <int num_dimensions, class coordT>
148{
149 operator=(c);
150}
151#endif
152
153template <int num_dimensions, class coordT>
154int
155BasicCoordinate<num_dimensions, coordT>::get_min_index()
156{
157 return 1;
158}
159
160template <int num_dimensions, class coordT>
161int
162BasicCoordinate<num_dimensions, coordT>::get_max_index()
163{
164 return num_dimensions;
165}
166
167template <int num_dimensions, class coordT>
168unsigned
169BasicCoordinate<num_dimensions, coordT>::size()
170{
171 return num_dimensions;
172}
173
174/*
175 numerical assignments
176*/
177template <int num_dimensions, class coordT>
178BasicCoordinate<num_dimensions, coordT>&
179BasicCoordinate<num_dimensions, coordT>::operator+=(const BasicCoordinate<num_dimensions, coordT>& c)
180{
181 for (int i = 1; i <= num_dimensions; i++)
182 (*this)[i] += c[i];
183 return *this;
184}
185
186template <int num_dimensions, class coordT>
187BasicCoordinate<num_dimensions, coordT>&
188BasicCoordinate<num_dimensions, coordT>::operator-=(const BasicCoordinate<num_dimensions, coordT>& c)
189{
190 for (int i = 1; i <= num_dimensions; i++)
191 (*this)[i] -= c[i];
192 return *this;
193}
194
195template <int num_dimensions, class coordT>
196BasicCoordinate<num_dimensions, coordT>&
197BasicCoordinate<num_dimensions, coordT>::operator*=(const BasicCoordinate<num_dimensions, coordT>& c)
198{
199 for (int i = 1; i <= num_dimensions; i++)
200 (*this)[i] *= c[i];
201 return *this;
202}
203
204template <int num_dimensions, class coordT>
205BasicCoordinate<num_dimensions, coordT>&
206BasicCoordinate<num_dimensions, coordT>::operator/=(const BasicCoordinate<num_dimensions, coordT>& c)
207{
208 for (int i = 1; i <= num_dimensions; i++)
209 (*this)[i] /= c[i];
210 return *this;
211}
212
213template <int num_dimensions, class coordT>
214BasicCoordinate<num_dimensions, coordT>&
215BasicCoordinate<num_dimensions, coordT>::operator+=(const coordT& a)
216{
217 for (int i = 1; i <= num_dimensions; i++)
218 (*this)[i] += a;
219 return *this;
220}
221
222template <int num_dimensions, class coordT>
223BasicCoordinate<num_dimensions, coordT>&
224BasicCoordinate<num_dimensions, coordT>::operator-=(const coordT& a)
225{
226 for (int i = 1; i <= num_dimensions; i++)
227 (*this)[i] -= a;
228 return *this;
229}
230
231template <int num_dimensions, class coordT>
232BasicCoordinate<num_dimensions, coordT>&
233BasicCoordinate<num_dimensions, coordT>::operator*=(const coordT& a)
234{
235 for (int i = 1; i <= num_dimensions; i++)
236 (*this)[i] *= a;
237 return *this;
238}
239
240template <int num_dimensions, class coordT>
241BasicCoordinate<num_dimensions, coordT>&
242BasicCoordinate<num_dimensions, coordT>::operator/=(const coordT& a)
243{
244 for (int i = 1; i <= num_dimensions; i++)
245 (*this)[i] /= a;
246 return *this;
247}
248
249/*
250 numerical operators
251*/
252template <int num_dimensions, class coordT>
253BasicCoordinate<num_dimensions, coordT>
254BasicCoordinate<num_dimensions, coordT>::operator+(const BasicCoordinate<num_dimensions, coordT>& c) const
255{
256 BasicCoordinate<num_dimensions, coordT> tmp(*this);
257 tmp += c;
258 return tmp;
259}
260
261template <int num_dimensions, class coordT>
262BasicCoordinate<num_dimensions, coordT>
263BasicCoordinate<num_dimensions, coordT>::operator-(const BasicCoordinate<num_dimensions, coordT>& c) const
264{
265 BasicCoordinate<num_dimensions, coordT> tmp(*this);
266 tmp -= c;
267 return tmp;
268}
269
270template <int num_dimensions, class coordT>
271BasicCoordinate<num_dimensions, coordT>
272BasicCoordinate<num_dimensions, coordT>::operator*(const BasicCoordinate<num_dimensions, coordT>& c) const
273{
274 BasicCoordinate<num_dimensions, coordT> tmp(*this);
275 tmp *= c;
276 return tmp;
277}
278
279template <int num_dimensions, class coordT>
280BasicCoordinate<num_dimensions, coordT>
281BasicCoordinate<num_dimensions, coordT>::operator/(const BasicCoordinate<num_dimensions, coordT>& c) const
282{
283 BasicCoordinate<num_dimensions, coordT> tmp(*this);
284 tmp /= c;
285 return tmp;
286}
287
288template <int num_dimensions, class coordT>
289BasicCoordinate<num_dimensions, coordT>
290BasicCoordinate<num_dimensions, coordT>::operator+(const coordT& a) const
291{
292 BasicCoordinate<num_dimensions, coordT> tmp(*this);
293 tmp += a;
294 return tmp;
295}
296
297template <int num_dimensions, class coordT>
298BasicCoordinate<num_dimensions, coordT>
299BasicCoordinate<num_dimensions, coordT>::operator-(const coordT& a) const
300{
301 BasicCoordinate<num_dimensions, coordT> tmp(*this);
302 tmp -= a;
303 return tmp;
304}
305
306template <int num_dimensions, class coordT>
307BasicCoordinate<num_dimensions, coordT>
308BasicCoordinate<num_dimensions, coordT>::operator*(const coordT& a) const
309{
310 BasicCoordinate<num_dimensions, coordT> tmp(*this);
311 tmp *= a;
312 return tmp;
313}
314
315template <int num_dimensions, class coordT>
316BasicCoordinate<num_dimensions, coordT>
317BasicCoordinate<num_dimensions, coordT>::operator/(const coordT& a) const
318{
319 BasicCoordinate<num_dimensions, coordT> tmp(*this);
320 tmp /= a;
321 return tmp;
322}
323
324template <int num_dimensions, class coordT>
325BasicCoordinate<num_dimensions, coordT>
326BasicCoordinate<num_dimensions, coordT>::operator-() const
327{
328 BasicCoordinate<num_dimensions, coordT> tmp(0);
329 tmp -= (*this);
330 return tmp;
331}
332
333/*
334 External functions
335*/
336
337template <class T>
338BasicCoordinate<1, T>
339make_coordinate(const T& a1)
340{
341 BasicCoordinate<1, T> a;
342 a[1] = a1;
343 return a;
344}
345
346template <class T>
347BasicCoordinate<2, T>
348make_coordinate(const T& a1, const T& a2)
349{
350 BasicCoordinate<2, T> a;
351 a[1] = a1;
352 a[2] = a2;
353 return a;
354}
355
356template <class T>
357BasicCoordinate<3, T>
358make_coordinate(const T& a1, const T& a2, const T& a3)
359{
360 BasicCoordinate<3, T> a;
361 a[1] = a1;
362 a[2] = a2;
363 a[3] = a3;
364 return a;
365}
366
367template <class T>
368BasicCoordinate<4, T>
369make_coordinate(const T& a1, const T& a2, const T& a3, const T& a4)
370{
371 BasicCoordinate<4, T> a;
372 a[1] = a1;
373 a[2] = a2;
374 a[3] = a3;
375 a[4] = a4;
376 return a;
377}
378
379template <class T>
380BasicCoordinate<5, T>
381make_coordinate(const T& a1, const T& a2, const T& a3, const T& a4, const T& a5)
382{
383 BasicCoordinate<5, T> a;
384 a[1] = a1;
385 a[2] = a2;
386 a[3] = a3;
387 a[4] = a4;
388 a[5] = a5;
389 return a;
390}
391
392template <class T>
393BasicCoordinate<6, T>
394make_coordinate(const T& a1, const T& a2, const T& a3, const T& a4, const T& a5, const T& a6)
395{
396 BasicCoordinate<6, T> a;
397 a[1] = a1;
398 a[2] = a2;
399 a[3] = a3;
400 a[4] = a4;
401 a[5] = a5;
402 a[6] = a6;
403 return a;
404}
405
406template <int num_dimensions, class coordT>
407coordT
409{
410 return std::inner_product(p1.begin(), p1.end(), p2.begin(), coordT(0));
411}
412// TODO specialise for complex coordTs if you need them
413template <int num_dimensions, class coordT>
414double
416{
417#ifdef _MSC_VER
418 return static_cast<double>(std::inner_product(p1.begin(), p1.end(), p1.begin(), coordT(0)));
419#else
420 return static_cast<double>(inner_product<num_dimensions, coordT>(p1, p1));
421#endif
422}
423// TODO specialise for complex coordTs if you need them
424template <int num_dimensions, class coordT>
425double
427{
428 return std::sqrt(norm_squared(p1));
429}
430
431template <int num_dimensions, class coordT>
432double
437
438template <int num_dimensions, class coordT>
439double
441{
442 return std::acos(cos_angle(p1, p2));
443}
444
445template <int num_dimensions, class coordT>
446inline BasicCoordinate<num_dimensions + 1, coordT>
448{
450
451 *retval.begin() = a;
452 std::copy(c.begin(), c.end(), retval.begin() + 1);
453 return retval;
454}
455
456template <int num_dimensions, class coordT>
457BasicCoordinate<num_dimensions - 1, coordT>
459{
460 BasicCoordinate<num_dimensions - 1, coordT> retval;
461 std::copy(c.begin(), c.end() - 1, retval.begin());
462 return retval;
463}
464template <int num_dimensions, class coordT>
465inline BasicCoordinate<num_dimensions + 1, coordT>
467{
469
470 retval[num_dimensions + 1] = a;
471 std::copy(c.begin(), c.end(), retval.begin());
472 return retval;
473}
474
475template <int num_dimensions, class coordT>
476BasicCoordinate<num_dimensions - 1, coordT>
478{
479 BasicCoordinate<num_dimensions - 1, coordT> retval;
480
481 std::copy(c.begin() + 1, c.end(), retval.begin());
482 return retval;
483}
484template <int num_dimensions>
485inline BasicCoordinate<num_dimensions, float>
487{
489 for (int i = 1; i <= num_dimensions; ++i)
490 cfloat[i] = (float)cint[i];
491 return cfloat;
492}
493
494// helper functions for operator<()
495namespace detail
496{
497
498template <class coordT>
499inline bool
500coordinate_less_than_help(is_1d, const BasicCoordinate<1, coordT>& c1, const BasicCoordinate<1, coordT>& c2)
501{
502 return c1[1] < c2[1];
503}
504
505// specialisation for 2D, avoiding cut_first_dimension and hence potentially slow if it's not optimised away
506template <class coordT>
507inline bool
508coordinate_less_than_help(is_not_1d, const BasicCoordinate<2, coordT>& c1, const BasicCoordinate<2, coordT>& c2)
509{
510 return c1[1] < c2[1] || (c1[1] == c2[1] && c1[2] < c2[2]);
511}
512
513// specialisation for 3D, avoiding cut_first_dimension and hence potentially slow if it's not optimised away
514template <class coordT>
515inline bool
516coordinate_less_than_help(is_not_1d, const BasicCoordinate<3, coordT>& c1, const BasicCoordinate<3, coordT>& c2)
517{
518 return c1[1] < c2[1] || (c1[1] == c2[1] && (c1[2] < c2[2] || (c1[2] == c2[2] && c1[3] < c2[3])));
519}
520
521template <int num_dimensions, class coordT>
522inline bool
523coordinate_less_than_help(is_not_1d,
524 const BasicCoordinate<num_dimensions, coordT>& c1,
525 const BasicCoordinate<num_dimensions, coordT>& c2)
526{
527 return c1[1] < c2[1] || (c1[1] == c2[1] && cut_first_dimension(c1) < cut_first_dimension(c2));
528}
529
530} // end namespace detail
531
532// generic definition
533template <int num_dimensions, class coordT>
534bool
536{
537 return detail::coordinate_less_than_help(detail::test_if_1d<num_dimensions>(), *this, c);
538}
539
540END_NAMESPACE_STIR
class BasicCoordinate<int num_dimensions, typename coordT> defines num_dimensions -dimensional coordi...
Definition BasicCoordinate.h:57
BasicCoordinate()
default constructor. NO initialisation
Definition BasicCoordinate.inl:136
BasicCoordinate & operator=(const BasicCoordinate &c)
assignment
Definition BasicCoordinate.inl:121
bool operator==(const BasicCoordinate &c) const
comparison
Definition BasicCoordinate.inl:111
coordT & operator[](const int d)
Return value at index t (which is 1-based)
Definition BasicCoordinate.inl:72
void fill(const coordT &)
fill elements with value
Definition BasicCoordinate.inl:130
coordT & at(const int d)
Return value at index t (which is 1-based), but with range checking (throws std::out_of_range)
Definition BasicCoordinate.inl:90
bool operator<(const BasicCoordinate &c) const
less-than (using lexical ordering)
Definition BasicCoordinate.inl:535
BasicCoordinate< num_dimensions+1, coordT > join(const coordT &a, const BasicCoordinate< num_dimensions, coordT > &c)
make a longer BasicCoordinate, by prepending c with the single coordT
Definition BasicCoordinate.inl:447
BasicCoordinate< num_dimensions - 1, coordT > cut_last_dimension(const BasicCoordinate< num_dimensions, coordT > &c)
make a shorter BasicCoordinate, by cutting the last element from c
Definition BasicCoordinate.inl:458
coordT inner_product(const BasicCoordinate< num_dimensions, coordT > &p1, const BasicCoordinate< num_dimensions, coordT > &p2)
compute sum_i p1[i] * p2[i]
Definition BasicCoordinate.inl:408
double norm(const BasicCoordinate< num_dimensions, coordT > &p1)
compute sqrt(inner_product(p1,p1))
Definition BasicCoordinate.inl:426
double angle(const BasicCoordinate< num_dimensions, coordT > &p1, const BasicCoordinate< num_dimensions, coordT > &p2)
compute angle between 2 directions
Definition BasicCoordinate.inl:440
BasicCoordinate< num_dimensions, float > convert_int_to_float(const BasicCoordinate< num_dimensions, int > &cint)
converts a BasicCoordinate<int> to BasicCoordinate<float>
Definition BasicCoordinate.inl:486
double norm_squared(const BasicCoordinate< num_dimensions, coordT > &p1)
compute (inner_product(p1,p1))
Definition BasicCoordinate.inl:415
BasicCoordinate< num_dimensions - 1, coordT > cut_first_dimension(const BasicCoordinate< num_dimensions, coordT > &c)
make a shorter BasicCoordinate, by cutting the first element from c
Definition BasicCoordinate.inl:477
double cos_angle(const BasicCoordinate< num_dimensions, coordT > &p1, const BasicCoordinate< num_dimensions, coordT > &p2)
compute cos of the angle between 2 directions
Definition BasicCoordinate.inl:433
a templated class used to check if it's a 1D array or not This class only exists to allow a work-arou...
Definition test_if_1d.h:71
Classes for use in implementation of stir::Array, stir::BasicCoordinate etc to test if it's a 1D arra...