bresenham.hpp
Go to the documentation of this file.
1 // Copyright 2023 Ekumen, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef BELUGA_ALGORITHM_RAYCASTING_BRESENHAM_HPP
16 #define BELUGA_ALGORITHM_RAYCASTING_BRESENHAM_HPP
17 
18 #include <cstdint>
19 #include <utility>
20 
21 #include <range/v3/view/all.hpp>
22 #include <range/v3/view/take_while.hpp>
23 
24 #include <Eigen/Core>
25 
31 namespace beluga {
32 
34 class Bresenham2i {
35  public:
37  enum Variant : std::uint8_t {
38  kStandard = 0,
40  };
42 
44 
50  template <class Vector2, typename Integer = typename Vector2::Scalar>
51  class Line : public ranges::view_interface<Line<Vector2, Integer>> {
52  public:
54  class iterator { // NOLINT(readability-identifier-naming)
55  public:
57  struct sentinel {
59  bool operator==(const iterator& other) const { return other == *this; }
60 
62  bool operator!=(const iterator& other) const { return !(other == *this); }
63  };
64 
66  using iterator_category = std::forward_iterator_tag;
67 
69  using difference_type = std::ptrdiff_t;
70 
73 
75  using pointer = Vector2*;
76 
78  using reference = Vector2&;
79 
81  iterator() = default;
82 
84  explicit iterator(const Line* line) : current_point_(line->p0_), x_(line->p0_.x()), y_(line->p0_.y()) {
85  xspan_ = line->p1_.x() - line->p0_.x();
86  xstep_ = static_cast<decltype(xspan_)>(1);
87  if (xspan_ < 0) {
88  xspan_ = -xspan_;
89  xstep_ = -xstep_;
90  }
91 
92  yspan_ = line->p1_.y() - line->p0_.y();
93  ystep_ = static_cast<decltype(yspan_)>(1);
94  if (yspan_ < 0) {
95  yspan_ = -yspan_;
96  ystep_ = -ystep_;
97  }
98 
99  if (xspan_ < yspan_) {
100  using std::swap;
101  swap(x_, y_);
102  swap(xspan_, yspan_);
103  swap(xstep_, ystep_);
104  reversed_ = true;
105  }
106 
107  dxspan_ = 2 * xspan_;
108  dyspan_ = 2 * yspan_;
109 
112  }
113 
116  iterator other = *this;
117  this->operator++();
118  return other;
119  }
120 
123  if (checks_ == 0) {
124  if (++step_ > xspan_) {
125  return *this;
126  }
127  x_ += xstep_;
128  error_ += dyspan_;
129  ++checks_;
130  if (error_ > dxspan_) {
131  y_ += ystep_;
132  error_ -= dxspan_;
133  if (modified_) {
134  ++checks_;
135  ++checks_;
136  }
137  }
138  }
139 
140  if (checks_ > 1) {
141  if (checks_ > 2) {
142  --checks_;
143  if (error_ + prev_error_ <= dxspan_) {
144  step_to(x_, y_ - ystep_);
145  return *this;
146  }
147  }
148 
149  --checks_;
150  if (error_ + prev_error_ >= dxspan_) {
151  step_to(x_ - xstep_, y_);
152  return *this;
153  }
154  }
155 
156  --checks_;
157  step_to(x_, y_);
159  return *this;
160  }
161 
163  const Vector2& operator*() const { return current_point_; }
164 
166  const Vector2* operator->() const { return &current_point_; }
167 
169  bool operator==(const iterator& other) const {
170  return x_ == other.x_ && y_ == other.y_ && xstep_ == other.xstep_ && ystep_ == other.ystep_ &&
171  xspan_ == other.xspan_ && yspan_ == other.yspan_ && step_ == other.step_ && checks_ == other.checks_ &&
172  modified_ == other.modified_ && reversed_ == other.reversed_;
173  }
174 
176  bool operator!=(const iterator& other) const { return !(*this == other); }
177 
179  bool operator==(const sentinel&) const { return step_ > xspan_; }
180 
182  bool operator!=(const sentinel& other) const { return !(*this == other); }
183 
184  private:
185  void step_to(Integer x, Integer y) {
186  if (reversed_) {
187  using std::swap;
188  swap(x, y);
189  }
190  current_point_.x() = x;
191  current_point_.y() = y;
192  }
193 
195  Integer x_{}, y_{};
196  Integer xspan_{}, yspan_{};
197  Integer dxspan_, dyspan_{};
198  Integer xstep_{}, ystep_{}, step_{};
199  Integer prev_error_{}, error_{};
200 
201  std::size_t checks_{0};
202  bool modified_{false};
203  bool reversed_{false};
204  };
205 
207  Line() = default;
208 
210 
215  explicit Line(Vector2 p0, Vector2 p1, Variant variant)
216  : p0_(std::move(p0)), p1_(std::move(p1)), variant_(variant) {}
217 
219  [[nodiscard]] auto begin() const { return Line::iterator{this}; }
220 
222  [[nodiscard]] auto end() const { return typename Line::iterator::sentinel{}; }
223 
224  private:
225  friend class iterator;
226 
230  };
231 
233  Bresenham2i() noexcept = default;
234 
236  Bresenham2i(const Bresenham2i&) noexcept = default;
237 
239  Bresenham2i(Bresenham2i&&) noexcept = default;
240 
242  Bresenham2i& operator=(const Bresenham2i&) noexcept = default;
243 
245  Bresenham2i& operator=(Bresenham2i&&) noexcept = default;
246 
248  explicit Bresenham2i(Variant variant) noexcept : variant_(variant) {}
249 
251 
257  template <class Vector2i = Eigen::Vector2i>
258  auto operator()(Vector2i p0, Vector2i p1) const {
259  return Line{std::move(p0), std::move(p1), variant_};
260  }
261 
262  private:
264 };
265 
266 } // namespace beluga
267 
268 #endif
beluga::Bresenham2i::Line::iterator::modified_
bool modified_
Definition: bresenham.hpp:202
beluga::Bresenham2i::Line::iterator::operator++
iterator & operator++()
Prefix operator overload.
Definition: bresenham.hpp:122
beluga::Bresenham2i::Line::iterator::operator->
const Vector2 * operator->() const
Arrow operator overload (only const).
Definition: bresenham.hpp:166
beluga::Bresenham2i::Line::iterator::xspan_
Integer xspan_
Definition: bresenham.hpp:196
beluga::swap
constexpr void swap(CircularArray< T, N, F > &a, CircularArray< T, N, G > &b)
Swaps arrays a and b.
Definition: circular_array.hpp:523
beluga::Bresenham2i::Line::end
auto end() const
Returns a sentinel as past-of-end iterator.
Definition: bresenham.hpp:222
beluga::Bresenham2i::Line::iterator::checks_
std::size_t checks_
Definition: bresenham.hpp:201
beluga::Bresenham2i::Line::Line
Line(Vector2 p0, Vector2 p1, Variant variant)
Constructs a Bresenham's 2D line drawing.
Definition: bresenham.hpp:215
beluga::Bresenham2i::Line::iterator::operator!=
bool operator!=(const sentinel &other) const
Sentinel inequality operator overload.
Definition: bresenham.hpp:182
beluga::Bresenham2i::Line::iterator::pointer
Vector2 * pointer
Pointer to iterated value type.
Definition: bresenham.hpp:75
beluga::Bresenham2i::Line
Bresenham's 2D line drawing as a range.
Definition: bresenham.hpp:51
beluga::Bresenham2i::kStandard
@ kStandard
Standard Bresenham's algorithm.
Definition: bresenham.hpp:38
beluga::Bresenham2i::Line::iterator::sentinel::operator!=
bool operator!=(const iterator &other) const
Inequality operator overload, for symmetry (as required by ranges::sentinel_for).
Definition: bresenham.hpp:62
beluga::Bresenham2i::Line::iterator::x_
Integer x_
Definition: bresenham.hpp:195
beluga::Bresenham2i::Line::iterator::prev_error_
Integer prev_error_
Definition: bresenham.hpp:199
beluga::Bresenham2i::Line::iterator::sentinel::operator==
bool operator==(const iterator &other) const
Equality operator overload, for symmetry (as required by ranges::sentinel_for).
Definition: bresenham.hpp:59
beluga::Bresenham2i::Line::iterator::dxspan_
Integer dxspan_
Definition: bresenham.hpp:197
beluga::Bresenham2i::Line::iterator::difference_type
std::ptrdiff_t difference_type
Iterator difference type (as required by ranges::view_).
Definition: bresenham.hpp:69
beluga::Bresenham2i::Line::iterator::y_
Integer y_
Definition: bresenham.hpp:195
Vector2
Vector< Scalar, 2, Options > Vector2
beluga::Bresenham2i::Line::iterator::ystep_
Integer ystep_
Definition: bresenham.hpp:198
beluga::Bresenham2i::Bresenham2i
Bresenham2i() noexcept=default
Constructs standard Bresenham 2D line drawing algorithm.
beluga::Bresenham2i::Line::iterator::step_to
void step_to(Integer x, Integer y)
Definition: bresenham.hpp:185
beluga::Bresenham2i::Line::begin
auto begin() const
Returns an iterator pointing to the first point in the line.
Definition: bresenham.hpp:219
beluga::Bresenham2i::Line::iterator::operator++
iterator operator++(int)
Post-fix operator overload.
Definition: bresenham.hpp:115
beluga::Bresenham2i::Line::iterator::iterator
iterator(const Line *line)
Constructs a Bresenham's 2D line iterator.
Definition: bresenham.hpp:84
beluga::Bresenham2i::Line::p1_
Vector2 p1_
Definition: bresenham.hpp:228
beluga::Bresenham2i::Variant
Variant
Bresenham's 2D line drawing algorithm variants.
Definition: bresenham.hpp:37
beluga::Bresenham2i::Line::iterator::iterator_category
std::forward_iterator_tag iterator_category
Iterator category tag.
Definition: bresenham.hpp:66
beluga::Bresenham2i::Line::variant_
Variant variant_
Definition: bresenham.hpp:229
beluga::Bresenham2i::Line::iterator::operator*
const Vector2 & operator*() const
Dereference operator overload (only const).
Definition: bresenham.hpp:163
beluga::Bresenham2i::Line::iterator::error_
Integer error_
Definition: bresenham.hpp:199
beluga::Bresenham2i::operator()
auto operator()(Vector2i p0, Vector2i p1) const
Computes 2D line from p0 to p1.
Definition: bresenham.hpp:258
beluga::Bresenham2i::variant_
Variant variant_
Definition: bresenham.hpp:263
beluga::Bresenham2i::Line::iterator::operator!=
bool operator!=(const iterator &other) const
Inequality operator overload (as required by std::forward_iterator).
Definition: bresenham.hpp:176
beluga::Bresenham2i::Line::iterator::xstep_
Integer xstep_
Definition: bresenham.hpp:198
beluga::Bresenham2i::Line::iterator::operator==
bool operator==(const sentinel &) const
Sentinel equality operator overload.
Definition: bresenham.hpp:179
std
Definition: circular_array.hpp:529
beluga::Bresenham2i::Line::iterator::iterator
iterator()=default
Default constructor.
beluga::Bresenham2i::Line::iterator::reversed_
bool reversed_
Definition: bresenham.hpp:203
beluga::Bresenham2i::Line::iterator::dyspan_
Integer dyspan_
Definition: bresenham.hpp:197
beluga::Bresenham2i
Bresenham's 2D line drawing algorithm, optimized for integer arithmetic.
Definition: bresenham.hpp:34
beluga::Bresenham2i::Line::iterator::operator==
bool operator==(const iterator &other) const
Equality operator overload (as required by std::forward_iterator).
Definition: bresenham.hpp:169
beluga::Bresenham2i::Line::iterator::current_point_
Vector2 current_point_
Definition: bresenham.hpp:194
beluga::Bresenham2i::Line::Line
Line()=default
Constructs point line.
beluga::Bresenham2i::Line::iterator::step_
Integer step_
Definition: bresenham.hpp:198
beluga::Bresenham2i::kModified
@ kModified
Definition: bresenham.hpp:39
beluga::Bresenham2i::Line::iterator::reference
Vector2 & reference
Reference to iterated value type.
Definition: bresenham.hpp:78
beluga::Bresenham2i::Line::iterator
Bresenham's 2D line drawing iterator, one cell at a time.
Definition: bresenham.hpp:54
beluga::Bresenham2i::Line::p0_
Vector2 p0_
Definition: bresenham.hpp:227
beluga::Bresenham2i::Line::iterator::value_type
Vector2 value_type
Iterated value type.
Definition: bresenham.hpp:72
beluga::Bresenham2i::Line::iterator::yspan_
Integer yspan_
Definition: bresenham.hpp:196
beluga::Bresenham2i::Line::iterator::sentinel
Past-of-end iterator sentinel.
Definition: bresenham.hpp:57
beluga
The main Beluga namespace.
Definition: 3d_embedding.hpp:21


beluga
Author(s):
autogenerated on Tue Jul 16 2024 02:59:53