Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
raytrace_line_2d.hpp
1 // Copyright (c) 2008, 2013, Willow Garage, Inc.
2 // All rights reserved.
3 //
4 // Software License Agreement (BSD License 2.0)
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 // * Neither the name of Willow Garage, Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Author: Eitan Marder-Eppstein
34 // David V. Lu!!
35 
36 #ifndef NAV2_UTIL__RAYTRACE_LINE_2D_HPP_
37 #define NAV2_UTIL__RAYTRACE_LINE_2D_HPP_
38 
39 #include <limits.h>
40 #include <algorithm>
41 #include <cmath>
42 
43 namespace nav2_util
44 {
45 
49 inline int sign(int x)
50 {
51  return x > 0 ? 1 : -1;
52 }
53 
58 template<class ActionType>
59 inline void bresenham2D(
60  ActionType at, unsigned int abs_da, unsigned int abs_db, int error_b,
61  int offset_a, int offset_b, unsigned int offset,
62  unsigned int max_length)
63 {
64  unsigned int end = std::min(max_length, abs_da);
65  for (unsigned int i = 0; i < end; ++i) {
66  at(offset);
67  offset += offset_a;
68  error_b += abs_db;
69  if ((unsigned int)error_b >= abs_da) {
70  offset += offset_b;
71  error_b -= abs_da;
72  }
73  }
74  at(offset);
75 }
76 
89 template<class ActionType>
90 inline void raytraceLine(
91  ActionType at, unsigned int x0, unsigned int y0, unsigned int x1,
92  unsigned int y1, unsigned int step_x,
93  unsigned int max_length = UINT_MAX, unsigned int min_length = 0)
94 {
95  int dx_full = x1 - x0;
96  int dy_full = y1 - y0;
97 
98  // we need to chose how much to scale our dominant dimension,
99  // based on the maximum length of the line
100  double dist = std::hypot(dx_full, dy_full);
101  if (dist < min_length) {
102  return;
103  }
104 
105  unsigned int min_x0, min_y0;
106  if (dist > 0.0) {
107  // Adjust starting point and offset to start from min_length distance
108  min_x0 = (unsigned int)(x0 + dx_full / dist * min_length);
109  min_y0 = (unsigned int)(y0 + dy_full / dist * min_length);
110  } else {
111  // dist can be 0 if [x0, y0]==[x1, y1].
112  // In this case only this cell should be processed.
113  min_x0 = x0;
114  min_y0 = y0;
115  }
116  unsigned int offset = min_y0 * step_x + min_x0;
117 
118  int dx = x1 - min_x0;
119  int dy = y1 - min_y0;
120 
121  unsigned int abs_dx = abs(dx);
122  unsigned int abs_dy = abs(dy);
123 
124  int offset_dx = sign(dx);
125  int offset_dy = sign(dy) * step_x;
126 
127  double scale = (dist == 0.0) ? 1.0 : std::min(1.0, max_length / dist);
128  // if x is dominant
129  if (abs_dx >= abs_dy) {
130  int error_y = abs_dx / 2;
131 
132  bresenham2D(
133  at, abs_dx, abs_dy, error_y, offset_dx, offset_dy, offset, (unsigned int)(scale * abs_dx));
134  return;
135  }
136 
137  // otherwise y is dominant
138  int error_x = abs_dy / 2;
139 
140  bresenham2D(
141  at, abs_dy, abs_dx, error_x, offset_dy, offset_dx, offset, (unsigned int)(scale * abs_dy));
142 }
143 
144 } // namespace nav2_util
145 
146 #endif // NAV2_UTIL__RAYTRACE_LINE_2D_HPP_