STIR  6.2.0
LORCoordinates.h
Go to the documentation of this file.
1 //
2 //
3 #ifndef __stir_LORCoordinates_H__
4 #define __stir_LORCoordinates_H__
5 
16 /*
17  Copyright (C) 2004 - 2009-06-22, Hammersmith Imanet Ltd
18  Copyright (C) 2011-07-01 - 2013, Kris Thielemans
19  Copyright 2017 ETH Zurich, Institute of Particle Physics and Astrophysics
20  This file is part of STIR.
21 
22  SPDX-License-Identifier: Apache-2.0
23 
24  See STIR/LICENSE.txt for details
25 */
26 
28 #include "stir/Succeeded.h"
29 
30 START_NAMESPACE_STIR
31 
32 // predeclarations to allow cross-referencing
33 template <class coordT>
34 class LOR;
35 template <class coordT>
37 template <class coordT>
39 template <class coordT>
41 template <class coordT>
42 class LORAs2Points;
43 
57 template <class coordT>
58 class LOR
59 {
60 public:
61  virtual ~LOR() {}
62 
63  virtual LOR* clone() const = 0;
64 
66  virtual bool is_swapped() const = 0;
67 
68  virtual Succeeded change_representation(LORInCylinderCoordinates<coordT>&, const double radius) const = 0;
69  virtual Succeeded change_representation(LORInAxialAndNoArcCorrSinogramCoordinates<coordT>&, const double radius) const = 0;
70  virtual Succeeded change_representation(LORInAxialAndSinogramCoordinates<coordT>&, const double radius) const = 0;
71  virtual Succeeded get_intersections_with_cylinder(LORAs2Points<coordT>&, const double radius) const = 0;
72 };
73 
79 template <class coordT>
81 {
82 private:
83  // sorry: has to be first to give the compiler a better chance of inlining
84  void check_state() const
85  {
86  assert(0 <= _psi);
87  assert(_psi < static_cast<coordT>(2 * _PI));
88  }
89 
90 public:
91  coordT psi() const
92  {
93  check_state();
94  return _psi;
95  }
96  coordT& psi()
97  {
98  check_state();
99  return _psi;
100  }
101  coordT z() const { return _z; }
102  coordT& z() { return _z; }
103 
104  inline PointOnCylinder();
105  inline PointOnCylinder(const coordT z, const coordT psi);
106 
107 private:
108  coordT _z;
109  coordT _psi;
110 };
111 
116 template <class coordT>
118 {
119 private:
120  // sorry: has to be first to give the compiler a better chance of inlining
121  void check_state() const { assert(_radius > 0); }
122 
123 protected:
124  explicit LORCylindricalCoordinates_z_and_radius(coordT radius = 1)
125  : _radius(radius)
126  {
127  check_state();
128  }
129  LORCylindricalCoordinates_z_and_radius(coordT z1, coordT z2, coordT radius)
130  : _radius(radius),
131  _z1(z1),
132  _z2(z2)
133  {
134  check_state();
135  }
136 
137  coordT z1() const
138  {
139  check_state();
140  return _z1;
141  }
142  coordT& z1()
143  {
144  check_state();
145  return _z1;
146  }
147  coordT z2() const
148  {
149  check_state();
150  return _z2;
151  }
152  coordT& z2()
153  {
154  check_state();
155  return _z2;
156  }
157 
158  coordT radius() const
159  {
160  check_state();
161  return _radius;
162  }
163 
164  inline void set_radius_no_check(const coordT new_radius)
165  {
166  check_state();
167  assert(new_radius > 0);
168  _z1 *= new_radius / _radius;
169  _z2 *= new_radius / _radius;
170  _radius = new_radius;
171  }
172  coordT _radius;
173 
174 protected:
175  coordT _z1;
176  coordT _z2;
177 };
178 
183 template <class coordT>
184 class LORInCylinderCoordinates : public LOR<coordT>
185 {
186 #ifdef SWIG
187  // SWIG needs this typedef to be public
188  public:
189 #endif
190  typedef LORInCylinderCoordinates<coordT> self_type;
191 
192 private:
193  void check_state() const
194  {
195  assert(_radius > 0);
196  }
197 
198 public:
199  const PointOnCylinder<coordT>& p1() const
200  {
201  return _p1;
202  }
204  {
205  return _p1;
206  }
207  const PointOnCylinder<coordT>& p2() const
208  {
209  return _p2;
210  }
212  {
213  return _p2;
214  }
215 
217 
220  bool is_swapped() const override
221  {
222  return false;
223  }
224  void reset(coordT radius = 1)
225  {
226  // set psi such that the new LOR does intersect that cylinder
227  _p1.psi() = 0;
228  _p2.psi() = static_cast<coordT>(_PI);
229  _radius = radius;
230  }
231  coordT radius() const
232  {
233  check_state();
234  return _radius;
235  }
236 
241  inline Succeeded set_radius(coordT new_radius)
242  {
243  check_state();
244  assert(new_radius > 0);
245  if (_radius == new_radius)
246  return Succeeded::yes;
247  // find minimum radius of a cylinder that is intersected by this LOR
248  const coordT min_radius = _radius * fabs(cos((_p1.psi() - _p2.psi()) / 2));
249  if (new_radius >= min_radius)
250  return Succeeded::no;
251  _p1.z() *= new_radius / _radius;
252  _p2.z() *= new_radius / _radius;
253  _radius = new_radius;
254  return Succeeded::yes;
255  }
256 
257  inline explicit LORInCylinderCoordinates(const coordT radius = 1);
258 
259  inline LORInCylinderCoordinates(const PointOnCylinder<coordT>& p1, const PointOnCylinder<coordT>& p2, const coordT radius = 1);
260 
262 
264 
265 #if 0
266  // disabled as would need radius argument as well, but currently not needed
267  inline
269 #endif
270 
271  self_type* clone() const override
272  {
273  return new self_type(*this);
274  }
275 
276  Succeeded change_representation(LORInCylinderCoordinates<coordT>&, const double radius) const override;
277 
278  Succeeded change_representation(LORInAxialAndNoArcCorrSinogramCoordinates<coordT>&, const double radius) const override;
279 
280  Succeeded change_representation(LORInAxialAndSinogramCoordinates<coordT>&, const double radius) const override;
281 
282  Succeeded get_intersections_with_cylinder(LORAs2Points<coordT>&, const double radius) const override;
283 
284 private:
287  coordT _radius;
288 };
289 
294 template <class coordT>
295 class LORAs2Points : public LOR<coordT>
296 {
297 #ifdef SWIG
298  // SWIG needs this typedef to be public
299  public:
300 #endif
302 
303 public:
304  const CartesianCoordinate3D<coordT>& p1() const
305  {
306  return _p1;
307  }
309  {
310  return _p1;
311  }
312  const CartesianCoordinate3D<coordT>& p2() const
313  {
314  return _p2;
315  }
317  {
318  return _p2;
319  }
320 
321  inline LORAs2Points();
322 
324 
325  inline LORAs2Points(const LORInCylinderCoordinates<coordT>& cyl_coords);
326 
328 
330 
332 
335  bool is_swapped() const override
336  {
337  return false;
338  }
339 
340  self_type* clone() const override
341  {
342  return new self_type(*this);
343  }
344 
345  Succeeded change_representation(LORInCylinderCoordinates<coordT>&, const double radius) const override;
346 
347  Succeeded change_representation(LORInAxialAndNoArcCorrSinogramCoordinates<coordT>&, const double radius) const override;
348 
349  Succeeded change_representation(LORInAxialAndSinogramCoordinates<coordT>&, const double radius) const override;
350 
351  Succeeded get_intersections_with_cylinder(LORAs2Points<coordT>&, const double radius) const override;
352 
354  Succeeded change_representation_for_block(LORInAxialAndNoArcCorrSinogramCoordinates<coordT>&, const double radius) const;
355 
356 private:
359 };
360 
365 template <class coordT>
367 {
368 private:
369 #ifdef SWIG
370  // SWIG needs this typedef to be public
371  public:
372 #endif
374 
375 private:
376  typedef LORCylindricalCoordinates_z_and_radius<coordT> private_base_type;
377  // sorry: has to be first to give the compiler a better chance of inlining
378  void check_state() const
379  {
380  assert(private_base_type::_radius > 0);
381  assert(_s > -private_base_type::_radius);
382  assert(_s < private_base_type::_radius);
383  assert(_phi < static_cast<coordT>(_PI));
384  assert(_phi >= 0);
385  }
386 
387 public:
388  coordT z1() const
389  {
390  check_state();
391  return private_base_type::z1();
392  }
393  coordT& z1()
394  {
395  check_state();
396  return private_base_type::z1();
397  }
398  coordT z2() const
399  {
400  check_state();
401  return private_base_type::z2();
402  }
403  coordT& z2()
404  {
405  check_state();
406  return private_base_type::z2();
407  }
408  coordT phi() const
409  {
410  check_state();
411  return _phi;
412  }
413  coordT& phi()
414  {
415  check_state();
416  return _phi;
417  }
418  coordT s() const
419  {
420  check_state();
421  return _s;
422  }
423  coordT& s()
424  {
425  check_state();
426  return _s;
427  }
428 
429  coordT beta() const
430  {
431  check_state();
432  return asin(_s / private_base_type::_radius);
433  }
434  bool is_swapped() const override
435  {
436  check_state();
437  return _swapped;
438  }
439  bool is_swapped()
440  {
441  check_state();
442  return _swapped;
443  }
444  inline explicit LORInAxialAndSinogramCoordinates(const coordT radius = 1);
445 
447 
452  const coordT z1, const coordT z2, const coordT phi, const coordT s, const coordT radius = 1, const bool swapped = false);
453 
455 
457 
458 #if 0
459  inline
461 #endif
462 
463  self_type* clone() const override
464  {
465  return new self_type(*this);
466  }
467 
468  void reset(coordT radius = 1)
469  {
470  // set such that the new LOR does intersect that cylinder
471  _s = 0;
472  private_base_type::_radius = radius;
473  }
474  coordT radius() const
475  {
476  check_state();
477  return private_base_type::_radius;
478  }
479 
480  inline Succeeded set_radius(const coordT new_radius)
481  {
482  if (private_base_type::_radius == new_radius)
483  return Succeeded::yes;
484  assert(new_radius > 0);
485  if (fabs(s()) >= new_radius)
486  return Succeeded::no;
487  this->set_radius_no_check(new_radius);
488  return Succeeded::yes;
489  }
490 
491  Succeeded change_representation(LORInCylinderCoordinates<coordT>&, const double radius) const override;
492 
493  Succeeded change_representation(LORInAxialAndNoArcCorrSinogramCoordinates<coordT>&, const double radius) const override;
494 
495  Succeeded change_representation(LORInAxialAndSinogramCoordinates<coordT>&, const double radius) const override;
496 
497  Succeeded get_intersections_with_cylinder(LORAs2Points<coordT>&, const double radius) const override;
498 
499 private:
500  coordT _phi;
501  coordT _s;
502  bool _swapped;
503 };
504 
509 template <class coordT>
511 {
512 private:
513 #ifdef SWIG
514  // SWIG needs this typedef to be public
515  public:
516 #endif
519 
520  // sorry: has to be first to give the compiler a better chance of inlining
521  void check_state() const
522  {
523  assert(private_base_type::_radius > 0);
524  assert(_beta >= static_cast<coordT>(-_PI / 2));
525  assert(_beta < static_cast<coordT>(_PI / 2));
526  assert(_phi < static_cast<coordT>(_PI));
527  assert(_phi >= 0);
528  }
529 
530 public:
531  coordT z1() const
532  {
533  check_state();
534  return private_base_type::z1();
535  }
536  coordT& z1()
537  {
538  check_state();
539  return private_base_type::z1();
540  }
541  coordT z2() const
542  {
543  check_state();
544  return private_base_type::z2();
545  }
546  coordT& z2()
547  {
548  check_state();
549  return private_base_type::z2();
550  }
551  coordT phi() const
552  {
553  check_state();
554  return _phi;
555  }
556  coordT& phi()
557  {
558  check_state();
559  return _phi;
560  }
561  coordT beta() const
562  {
563  check_state();
564  return _beta;
565  }
566  coordT& beta()
567  {
568  check_state();
569  return _beta;
570  }
571  bool is_swapped() const override
572  {
573  check_state();
574  return _swapped;
575  }
576  bool is_swapped()
577  {
578  check_state();
579  return _swapped;
580  }
581 
582  coordT s() const
583  {
584  check_state();
585  return private_base_type::_radius * sin(_beta);
586  }
587 
588  void reset(coordT radius = 1)
589  {
590  // set such that the new LOR does intersect that cylinder
591  _beta = 0;
592  private_base_type::_radius = radius;
593  }
594  coordT radius() const
595  {
596  check_state();
597  return private_base_type::_radius;
598  }
599 
600  inline Succeeded set_radius(const coordT new_radius)
601  {
602  if (private_base_type::_radius == new_radius)
603  return Succeeded::yes;
604  assert(new_radius > 0);
605  if (fabs(s()) >= new_radius)
606  return Succeeded::no;
607  this->set_radius_no_check(new_radius);
608  return Succeeded::yes;
609  }
610 
611  inline explicit LORInAxialAndNoArcCorrSinogramCoordinates(const coordT radius = 1);
612 
614 
619  const coordT z1, const coordT z2, const coordT phi, const coordT beta, const coordT radius = 1, const bool swapped = false);
620 
622 
624 
625 #if 0
626  inline
628 #endif
629 
630  self_type* clone() const override
631  {
632  return new self_type(*this);
633  }
634 
635  Succeeded change_representation(LORInCylinderCoordinates<coordT>&, const double radius) const override;
636 
637  Succeeded change_representation(LORInAxialAndNoArcCorrSinogramCoordinates<coordT>&, const double radius) const override;
638 
639  Succeeded change_representation(LORInAxialAndSinogramCoordinates<coordT>&, const double radius) const override;
640 
641  Succeeded get_intersections_with_cylinder(LORAs2Points<coordT>&, const double radius) const override;
642 
643 private:
644  coordT _phi;
645  coordT _beta;
646  bool _swapped;
647 };
648 
654 template <class coordT1, class coordT2>
655 inline Succeeded
661 template <class coordT1, class coordT2>
663  const LORAs2Points<coordT2>& coords,
664  const double radius);
669 template <class coordT1, class coordT2>
671  const LORAs2Points<coordT2>& cart_coords,
672  const double radius);
673 
678 template <class coordT1, class coordT2>
680  const LORAs2Points<coordT2>& cart_coords,
681  const double radius);
682 
683 END_NAMESPACE_STIR
684 
685 #include "stir/LORCoordinates.inl"
686 
687 #endif
Declaration of class stir::Succeeded.
#define _PI
The constant pi to high precision.
Definition: common.h:134
An internal class for LORs. Do not use.
Definition: LORCoordinates.h:117
a templated class for 3-dimensional coordinates.
Definition: CartesianCoordinate3D.h:52
Succeeded set_radius(coordT new_radius)
Changes the radius of the LOR.
Definition: LORCoordinates.h:241
bool is_swapped() const override
Return if the LOR direction is opposite from normal.
Definition: LORCoordinates.h:220
A class for a point on a cylinder.
Definition: LORCoordinates.h:80
bool is_swapped() const override
Return if the LOR direction is opposite from normal.
Definition: LORCoordinates.h:335
A class for LORs.
Definition: LORCoordinates.h:38
A class for LORs.
Definition: CListRecord.h:39
bool is_swapped() const override
Return if the LOR direction is opposite from normal.
Definition: LORCoordinates.h:434
bool is_swapped() const override
Return if the LOR direction is opposite from normal.
Definition: LORCoordinates.h:571
A class for LORs.
Definition: LORCoordinates.h:40
Succeeded find_LOR_intersections_with_cylinder(LORInAxialAndSinogramCoordinates< coordT1 > &lor, const LORAs2Points< coordT2 > &cart_coords, const double radius)
Given an LOR, find its intersection with a (infintely long) cylinder.
Definition: LORCoordinates.inl:392
A class for LORs.
Definition: LORCoordinates.h:36
Implementations for LORCoordinates.h.
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition: Succeeded.h:43
defines the stir::CartesianCoordinate3D<coordT> class
A base class for specifying an LOR with geometric coordinates.
Definition: LORCoordinates.h:34