STIR 6.4.0
overlap_interpolate.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2005- 2006, Hammersmith Imanet Ltd
5 This file is part of STIR.
6
7 SPDX-License-Identifier: Apache-2.0
8
9 See STIR/LICENSE.txt for details
10*/
18#include <algorithm>
19#include "boost/iterator/iterator_traits.hpp"
20
21START_NAMESPACE_STIR
22template <typename out_iter_t, typename out_coord_iter_t, typename in_iter_t, typename in_coord_iter_t>
23void
24overlap_interpolate(const out_iter_t out_begin,
25 const out_iter_t out_end,
26 const out_coord_iter_t out_coord_begin,
27 const out_coord_iter_t out_coord_end,
28 const in_iter_t in_begin,
29 in_iter_t in_end,
30 const in_coord_iter_t in_coord_begin,
31 const in_coord_iter_t in_coord_end,
32 const bool only_add_to_output,
33 const bool assign_rest_with_zeroes)
34{
35
36 if (out_begin == out_end)
37 return;
38 if (in_begin == in_end)
39 return;
40
41 // check sizes.
42 // these asserts can be disabled if we ever use this function with iterators
43 // that don't support the next 2 lines
44 assert(out_coord_end - out_coord_begin - 1 == (out_end - out_begin));
45 assert(in_coord_end - in_coord_begin - 1 == (in_end - in_begin));
46
47 out_iter_t out_iter = out_begin;
48 out_coord_iter_t out_coord_iter = out_coord_begin;
49
50 in_iter_t in_iter = in_begin;
51 in_coord_iter_t in_coord_iter = in_coord_begin;
52
53 // skip input to the left of the output range
54 assert(in_coord_iter + 1 != in_coord_end);
55 while (*(in_coord_iter + 1) <= *out_coord_iter)
56 {
57 ++in_coord_iter;
58 ++in_iter;
59 if (in_coord_iter + 1 == in_coord_end)
60 return;
61 }
62
63 // skip output to the left of the input range
64 assert(out_coord_iter + 1 != out_coord_end);
65 while (*(out_coord_iter + 1) <= *in_coord_iter)
66 {
67 if (!only_add_to_output && assign_rest_with_zeroes)
68 *out_iter *= 0; // note: use *= such that it works for multi-dim arrays
69 ++out_coord_iter;
70 ++out_iter;
71 if (out_coord_iter + 1 == out_coord_end)
72 return;
73 }
74
75 // now first in-box overlaps guaranteed with first out-box
76 assert(*(out_coord_iter + 1) > *in_coord_iter);
77 assert(*(in_coord_iter + 1) > *out_coord_iter);
78
79 // a typedef for the coordinate type
80 typedef typename boost::iterator_value<out_coord_iter_t>::type coord_t;
81
82 // find small number for comparisons.
83 // we'll take it 1000 times smaller than the minimum of the average out_box size or in_box size
84 const coord_t epsilon
85 = std::min(((*(out_coord_end - 1)) - (*out_coord_begin)) / ((out_coord_end - 1 - out_coord_begin) * 10000),
86 ((*(in_coord_end - 1)) - (*in_coord_begin)) / ((in_coord_end - 1 - in_coord_begin) * 10000));
87
88 // do actual interpolation
89 // we walk through the boxes, checking the overlap.
90 // after each step, we'll advance either in_iter or out_iter.
91 coord_t current_coord = std::max(*in_coord_iter, *out_coord_iter);
92 bool first_time_for_this_out_box = true;
93 while (true)
94 {
95 // right edge of in-box is beyond out-box
96 const bool in_beyond_out = *(in_coord_iter + 1) > *(out_coord_iter + 1);
97 const coord_t new_coord = in_beyond_out ? *(out_coord_iter + 1) : *(in_coord_iter + 1);
98#ifndef STIR_OVERLAP_NORMALISATION
99 const coord_t overlap = (new_coord - current_coord);
100#else
101 const coord_t overlap = (new_coord - current_coord) / (*(out_coord_iter + 1) - *(out_coord_iter));
102#endif
103 assert(overlap > -epsilon);
104
105 if (!only_add_to_output && first_time_for_this_out_box)
106 {
107 if (overlap > epsilon)
108 *out_iter = *in_iter * overlap;
109 else
110 *out_iter *= 0;
111 first_time_for_this_out_box = false;
112 }
113 else
114 {
115 if (overlap > epsilon)
116 *out_iter += *in_iter * overlap;
117 }
118 current_coord = new_coord;
119 if (in_beyond_out)
120 {
121 ++out_coord_iter;
122 ++out_iter;
123 if (out_iter == out_end)
124 {
125 assert(out_coord_iter + 1 == out_coord_end);
126 return; // all out-boxes are done
127 }
128 first_time_for_this_out_box = true;
129 }
130 else
131 {
132 ++in_coord_iter;
133 ++in_iter;
134 if (in_iter == in_end)
135 break;
136 }
137 } // end of while
138
139 assert(in_coord_iter + 1 == in_coord_end);
140 // fill rest of output with 0
141 if (!only_add_to_output && assign_rest_with_zeroes)
142 {
143 while (true)
144 {
145 ++out_iter;
146#ifndef NDEBUG
147 // increment just so we can check at the end that there is
148 // one more out_coord_iter than out_iter
149 ++out_coord_iter;
150#endif
151 if (out_iter == out_end)
152 break;
153 *out_iter *= 0; // note: use *= such that it works for multi-dim arrays
154 }
155 assert(out_coord_iter + 1 == out_coord_end);
156 }
157}
158
159END_NAMESPACE_STIR
void overlap_interpolate(VectorWithOffset< T > &out_data, const VectorWithOffset< T > &in_data, const float zoom, const float offset, const bool assign_rest_with_zeroes)
'overlap' interpolation (i.e. count preserving) for vectors.
Definition overlap_interpolate.cxx:102