Scroom 0.14-49-gb7ae7a6d
Loading...
Searching...
No Matches
linearsegment.hh
Go to the documentation of this file.
1/*
2 * Scroom - Generic viewer for 2D data
3 * Copyright (C) 2009-2026 Kees-Jan Dijkzeul
4 *
5 * SPDX-License-Identifier: LGPL-2.1
6 */
7
8#pragma once
9
10#include <cmath>
11#include <ostream>
12#include <type_traits>
13
14#include <boost/operators.hpp>
15
16#include <scroom/rounding.hh>
17
18namespace Scroom::Utils
19{
20 constexpr double epsilon = 1e-6;
21
22 template <typename T>
23 bool isZero(T v);
24
25 template <>
26 inline bool isZero<int>(int v)
27 {
28 return v == 0;
29 }
30
31 template <>
32 inline bool isZero<double>(double v)
33 {
34 return std::abs(v) < epsilon;
35 }
36
37 template <typename T>
38 bool areEqual(T a, T b)
39 {
40 return isZero(a - b);
41 }
42
43 template <typename T>
44 class Segment
45 : public boost::addable2<Segment<T>, T>
46 , public boost::subtractable2<Segment<T>, T>
47 , public boost::multipliable2<Segment<T>, T>
48 , public boost::dividable2<Segment<T>, T>
49 , public boost::andable<Segment<T>>
50 {
51 public:
52 using value_type = T;
53
55 : start(0)
56 , size(0)
57 {
58 }
59
61 : start(start_)
62 , size(size_)
63 {
64 normalize();
65 }
66
68 template <bool T_is_int = std::is_same_v<int, std::remove_cv_t<T>>>
69 explicit Segment(std::enable_if_t<!T_is_int, Segment<int> const&> other)
70 : start(other.getStart())
71 , size(other.getSize())
72 {
73 }
74
75 [[nodiscard]] Segment moveTo(value_type p) const { return Segment(p, size); }
76
77 [[nodiscard]] bool contains(value_type p) const { return start <= p && p < (start + size); }
78
79 [[nodiscard]] bool contains(const Segment<value_type>& other) const
80 {
81 return getStart() <= other.getStart() && other.getEnd() <= getEnd();
82 }
83
84 [[nodiscard]] bool intersects(const Segment<value_type>& other) const
85 {
86 return getStart() < other.getEnd() && other.getStart() < getEnd() && !isEmpty() && !other.isEmpty();
87 }
88
90
91 [[nodiscard]] Segment<value_type> intersection(const Segment<value_type>& other) const
92 {
93 const value_type newStart = std::max(getStart(), other.getStart());
94 const value_type newEnd = std::min(getEnd(), other.getEnd());
95 const value_type newSize = newEnd - newStart;
96
97 if(newSize >= 0)
98 {
99 return Segment<value_type>(newStart, newSize);
100 }
101
102 return Segment<value_type>(); // empty segment
103 }
104
105 void intersect(const Segment<value_type>& other) { *this = intersection(other); }
106
107 [[nodiscard]] Segment<value_type> before(value_type v) const
108 {
109 if(v < start)
110 {
111 return Segment<value_type>();
112 }
113 if(v < start + size)
114 {
115 return Segment<value_type>(start, v - start);
116 }
117 return *this;
118 }
119
120 [[nodiscard]] Segment<value_type> after(value_type v) const
121 {
122 if(v > start + size)
123 {
124 return Segment<value_type>();
125 }
126 if(v > start)
127 {
128 return Segment<value_type>(v, start + size - v);
129 }
130 return *this;
131 }
132
133 [[nodiscard]] value_type getStart() const { return start; }
134
135 [[nodiscard]] value_type getEnd() const { return start + size; }
136
137 [[nodiscard]] value_type getSize() const { return size; }
138
139 [[nodiscard]] bool isEmpty() const { return isZero(getSize()); }
140
141 bool operator==(const Segment<value_type>& other) const
142 {
143 if(isEmpty() != other.isEmpty())
144 {
145 return false;
146 }
147
148 if(isEmpty())
149 {
150 return true;
151 }
152
153 return areEqual(start, other.start) && areEqual(size, other.size);
154 }
155
156 bool operator!=(const Segment<value_type>& other) const { return !(*this == other); }
157
159 {
160 start += n;
161 return *this;
162 }
164 {
165 start -= n;
166 return *this;
167 }
169 {
170 start *= n;
171 size *= n;
172 return *this;
173 }
175 {
176 start /= n;
177 size /= n;
178 return *this;
179 }
181 {
182 intersect(other);
183 return *this;
184 }
186 {
187 const auto end = getEnd();
188 start = n;
189 setEnd(end);
190 }
191 void setSize(value_type n) { size = n; }
193 {
194 size = n - start;
195 normalize();
196 }
197
198 template <typename U>
199 [[nodiscard]] Segment<U> to() const
200 {
201 return {
202 static_cast<U>(start),
203 static_cast<U>(size),
204 };
205 }
206
207 private:
209 {
210 if(size < 0)
211 {
212 start += size;
213 size = -size;
214 }
215 }
216
217
220 };
221
222 template <typename T>
224 {
225 return Segment<T>(start, size);
226 }
227
228 template <typename T>
230 {
231 return Segment<T>(start, end - start);
232 }
233
234 template <typename T>
235 std::ostream& operator<<(std::ostream& os, const Segment<T>& s)
236 {
237 return os << '(' << s.getStart() << ',' << s.getSize() << ')';
238 }
239
244
245 template <typename T>
247 {
248 return s.getStart() + s.getSize() / 2;
249 }
250
251} // namespace Scroom::Utils
std::shared_ptr< A > a
Definition async-deleter-tests.cc:60
Blob::Ptr const b
Definition blob-tests.cc:118
Definition linearsegment.hh:50
T value_type
Definition linearsegment.hh:52
void intersect(const Segment< value_type > &other)
Definition linearsegment.hh:105
void setSize(value_type n)
Definition linearsegment.hh:191
bool operator==(const Segment< value_type > &other) const
Definition linearsegment.hh:141
Segment< value_type > & operator/=(value_type n)
Definition linearsegment.hh:174
Segment(std::enable_if_t<!T_is_int, Segment< int > const & > other)
Definition linearsegment.hh:69
Segment< value_type > before(value_type v) const
Definition linearsegment.hh:107
bool operator!=(const Segment< value_type > &other) const
Definition linearsegment.hh:156
value_type size
Definition linearsegment.hh:219
bool isEmpty() const
Definition linearsegment.hh:139
Segment< value_type > & operator&=(const Segment< value_type > &other)
Definition linearsegment.hh:180
void setStart(value_type n)
Definition linearsegment.hh:185
value_type getEnd() const
Definition linearsegment.hh:135
Segment< value_type > & operator+=(value_type n)
Definition linearsegment.hh:158
Segment()
Definition linearsegment.hh:54
Segment< value_type > & operator-=(value_type n)
Definition linearsegment.hh:163
bool contains(value_type p) const
Definition linearsegment.hh:77
bool intersects(const Segment< value_type > &other) const
Definition linearsegment.hh:84
value_type getStart() const
Definition linearsegment.hh:133
void setEnd(value_type n)
Definition linearsegment.hh:192
value_type start
Definition linearsegment.hh:218
Segment(value_type start_, value_type size_)
Definition linearsegment.hh:60
void normalize()
Definition linearsegment.hh:208
Segment< value_type > after(value_type v) const
Definition linearsegment.hh:120
Segment< U > to() const
Definition linearsegment.hh:199
value_type getSize() const
Definition linearsegment.hh:137
Segment< value_type > intersection(const Segment< value_type > &other) const
Definition linearsegment.hh:91
Segment< value_type > & operator*=(value_type n)
Definition linearsegment.hh:168
Segment moveTo(value_type p) const
Definition linearsegment.hh:75
bool contains(const Segment< value_type > &other) const
Definition linearsegment.hh:79
void reduceSizeToMultipleOf(value_type m)
Definition linearsegment.hh:89
PresentationInterfaceStub::Ptr const p
Definition determine-size-test.cc:172
Definition tweak-view.hh:22
constexpr double epsilon
Definition linearsegment.hh:20
bool isZero< int >(int v)
Definition linearsegment.hh:26
bool areEqual(T a, T b)
Definition linearsegment.hh:38
T center(Segment< T > s)
Definition linearsegment.hh:246
Segment< double > roundOutward(Segment< double > s)
Definition linearsegment.hh:240
bool isZero< double >(double v)
Definition linearsegment.hh:32
std::ostream & operator<<(std::ostream &os, const Segment< T > &s)
Definition linearsegment.hh:235
Segment< T > make_segment_from_start_end(T start, T end)
Definition linearsegment.hh:229
bool isZero(T v)
Segment< T > make_segment(T start, T size)
Definition linearsegment.hh:223
T round_up_to_multiple_of(T value, T factor)
Definition rounding.hh:38
T round_down_to_multiple_of(T value, T factor)
Definition rounding.hh:44
const SampleIterator< const uint8_t > start(nullptr, initial_offset, bps)
BitmapSurface::Ptr const s
Definition transformpresentation_test.cc:70