Gazebo Math

API Reference

7.7.0
gz/math/Line2.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 #ifndef GZ_MATH_LINE2_HH_
18 #define GZ_MATH_LINE2_HH_
19 
20 #include <algorithm>
21 #include <gz/math/Vector2.hh>
22 #include <gz/math/config.hh>
23 
24 namespace gz::math
25 {
26  // Inline bracket to help doxygen filtering.
27  inline namespace GZ_MATH_VERSION_NAMESPACE {
28  //
32  template<typename T>
33  class Line2
34  {
38  public: Line2(const math::Vector2<T> &_ptA, const math::Vector2<T> &_ptB)
39  {
40  this->Set(_ptA, _ptB);
41  }
42 
48  public: Line2(T _x1, T _y1, T _x2, T _y2)
49  {
50  this->Set(_x1, _y1, _x2, _y2);
51  }
52 
56  public: void Set(const math::Vector2<T> &_ptA,
57  const math::Vector2<T> &_ptB)
58  {
59  this->pts[0] = _ptA;
60  this->pts[1] = _ptB;
61  }
62 
68  public: void Set(T _x1, T _y1, T _x2, T _y2)
69  {
70  this->pts[0].Set(_x1, _y1);
71  this->pts[1].Set(_x2, _y2);
72  }
73 
80  public: T CrossProduct(const Line2<T> &_line) const
81  {
82  return (this->pts[0].X() - this->pts[1].X()) *
83  (_line[0].Y() -_line[1].Y()) -
84  (this->pts[0].Y() - this->pts[1].Y()) *
85  (_line[0].X() - _line[1].X());
86  }
87 
90  // (_pt.y - a.y) * (b.x - a.x) - (_pt.x - a.x) * (b.y - a.y)
93  public: T CrossProduct(const Vector2<T> &_pt) const
94  {
95  return (_pt.Y() - this->pts[0].Y()) *
96  (this->pts[1].X() - this->pts[0].X()) -
97  (_pt.X() - this->pts[0].X()) *
98  (this->pts[1].Y() - this->pts[0].Y());
99  }
100 
107  public: bool Collinear(const math::Vector2<T> &_pt,
108  double _epsilon = 1e-6) const
109  {
110  return math::equal(this->CrossProduct(_pt),
111  static_cast<T>(0), static_cast<T>(_epsilon));
112  }
113 
121  public: bool Parallel(const math::Line2<T> &_line,
122  double _epsilon = 1e-6) const
123  {
124  return math::equal(this->CrossProduct(_line),
125  static_cast<T>(0), static_cast<T>(_epsilon));
126  }
127 
135  public: bool Collinear(const math::Line2<T> &_line,
136  double _epsilon = 1e-6) const
137  {
138  return this->Parallel(_line, _epsilon) &&
139  this->Intersect(_line, _epsilon);
140  }
141 
147  public: bool OnSegment(const math::Vector2<T> &_pt,
148  double _epsilon = 1e-6) const
149  {
150  return this->Collinear(_pt, _epsilon) && this->Within(_pt, _epsilon);
151  }
152 
160  public: bool Within(const math::Vector2<T> &_pt,
161  double _epsilon = 1e-6) const
162  {
163  auto eps = static_cast<T>(_epsilon);
164  return _pt.X() <= std::max(this->pts[0].X(),
165  this->pts[1].X()) + eps &&
166  _pt.X() >= std::min(this->pts[0].X(),
167  this->pts[1].X()) - eps &&
168  _pt.Y() <= std::max(this->pts[0].Y(),
169  this->pts[1].Y()) + eps &&
170  _pt.Y() >= std::min(this->pts[0].Y(),
171  this->pts[1].Y()) - eps;
172  }
173 
179  public: bool Intersect(const Line2<T> &_line,
180  double _epsilon = 1e-6) const
181  {
182  static math::Vector2<T> ignore;
183  return this->Intersect(_line, ignore, _epsilon);
184  }
185 
194  public: bool Intersect(const Line2<T> &_line, math::Vector2<T> &_pt,
195  double _epsilon = 1e-6) const
196  {
197  T d = this->CrossProduct(_line);
198 
199  // d is zero if the two line are collinear. Must check special
200  // cases.
201  if (math::equal(d, static_cast<T>(0), static_cast<T>(_epsilon)))
202  {
203  // Check if _line's starting point is on the line.
204  if (this->Within(_line[0], _epsilon))
205  {
206  _pt = _line[0];
207  return true;
208  }
209  // Check if _line's ending point is on the line.
210  else if (this->Within(_line[1], _epsilon))
211  {
212  _pt = _line[1];
213  return true;
214  }
215  // Other wise return false.
216  else
217  return false;
218  }
219 
220  _pt.X((_line[0].X() - _line[1].X()) *
221  (this->pts[0].X() * this->pts[1].Y() -
222  this->pts[0].Y() * this->pts[1].X()) -
223  (this->pts[0].X() - this->pts[1].X()) *
224  (_line[0].X() * _line[1].Y() - _line[0].Y() * _line[1].X()));
225 
226  _pt.Y((_line[0].Y() - _line[1].Y()) *
227  (this->pts[0].X() * this->pts[1].Y() -
228  this->pts[0].Y() * this->pts[1].X()) -
229  (this->pts[0].Y() - this->pts[1].Y()) *
230  (_line[0].X() * _line[1].Y() - _line[0].Y() * _line[1].X()));
231 
232  _pt /= d;
233 
234  if (_pt.X() < std::min(this->pts[0].X(), this->pts[1].X()) ||
235  _pt.X() > std::max(this->pts[0].X(), this->pts[1].X()) ||
236  _pt.X() < std::min(_line[0].X(), _line[1].X()) ||
237  _pt.X() > std::max(_line[0].X(), _line[1].X()))
238  {
239  return false;
240  }
241 
242  if (_pt.Y() < std::min(this->pts[0].Y(), this->pts[1].Y()) ||
243  _pt.Y() > std::max(this->pts[0].Y(), this->pts[1].Y()) ||
244  _pt.Y() < std::min(_line[0].Y(), _line[1].Y()) ||
245  _pt.Y() > std::max(_line[0].Y(), _line[1].Y()))
246  {
247  return false;
248  }
249 
250  return true;
251  }
252 
255  public: T Length() const
256  {
257  return static_cast<T>(this->pts[0].Distance(this->pts[1]));
258  }
259 
262  public: double Slope() const
263  {
264  if (math::equal(this->pts[1].X(), this->pts[0].X()))
265  return NAN_D;
266 
267  return (this->pts[1].Y() - this->pts[0].Y()) /
268  static_cast<double>(this->pts[1].X() - this->pts[0].X());
269  }
270 
274  public: bool operator==(const Line2<T> &_line) const
275  {
276  return this->pts[0] == _line[0] && this->pts[1] == _line[1];
277  }
278 
282  public: bool operator!=(const Line2<T> &_line) const
283  {
284  return !(*this == _line);
285  }
286 
290  public: math::Vector2<T> operator[](size_t _index) const
291  {
292  return this->pts[clamp(_index, GZ_ZERO_SIZE_T, GZ_ONE_SIZE_T)];
293  }
294 
299  public: friend std::ostream &operator<<(
300  std::ostream &_out, const Line2<T> &_line)
301  {
302  _out << _line[0] << " " << _line[1];
303  return _out;
304  }
305 
306  private: math::Vector2<T> pts[2];
307  };
308 
309 
313  } // namespace GZ_MATH_VERSION_NAMESPACE
314 } // namespace gz::math
315 #endif // GZ_MATH_LINE2_HH_