All Classes Namespaces Files Functions Variables Typedefs Friends Macros Pages
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 _IGNITION_LINE2_HH_
18 #define _IGNITION_LINE2_HH_
19 
20 #include <algorithm>
21 #include <ignition/math/Vector2.hh>
23 
24 namespace ignition
25 {
26  namespace math
27  {
31  template<typename T>
32  class Line2
33  {
37  public: Line2(const math::Vector2<T> &_ptA, const math::Vector2<T> &_ptB)
38  {
39  this->Set(_ptA, _ptB);
40  }
41 
47  public: Line2(double _x1, double _y1, double _x2, double _y2)
48  {
49  this->Set(_x1, _y1, _x2, _y2);
50  }
51 
55  public: void Set(const math::Vector2<T> &_ptA,
56  const math::Vector2<T> &_ptB)
57  {
58  this->pts[0] = _ptA;
59  this->pts[1] = _ptB;
60  }
61 
67  public: void Set(double _x1, double _y1, double _x2, double _y2)
68  {
69  this->pts[0].Set(_x1, _y1);
70  this->pts[1].Set(_x2, _y2);
71  }
72 
79  public: double CrossProduct(const Line2<T> &_line) const
80  {
81  return (this->pts[0].X() - this->pts[1].X()) *
82  (_line[0].Y() -_line[1].Y()) -
83  (this->pts[0].Y() - this->pts[1].Y()) *
84  (_line[0].X() - _line[1].X());
85  }
86 
89  // (_pt.y - a.y) * (b.x - a.x) - (_pt.x - a.x) * (b.y - a.y)
92  public: double CrossProduct(const Vector2<T> &_pt) const
93  {
94  return (_pt.Y() - this->pts[0].Y()) *
95  (this->pts[1].X() - this->pts[0].X()) -
96  (_pt.X() - this->pts[0].X()) *
97  (this->pts[1].Y() - this->pts[0].Y());
98  }
99 
106  public: bool Collinear(const math::Vector2<T> &_pt,
107  double _epsilon = 1e-6) const
108  {
109  return math::equal(this->CrossProduct(_pt),
110  static_cast<T>(0), _epsilon);
111  }
112 
120  public: bool Parallel(const math::Line2<T> &_line,
121  double _epsilon = 1e-6) const
122  {
123  return math::equal(this->CrossProduct(_line),
124  static_cast<T>(0), _epsilon);
125  }
126 
134  public: bool Collinear(const math::Line2<T> &_line,
135  double _epsilon = 1e-6) const
136  {
137  return this->Parallel(_line, _epsilon) &&
138  this->Intersect(_line, _epsilon);
139  }
140 
146  public: bool OnSegment(const math::Vector2<T> &_pt,
147  double _epsilon = 1e-6) const
148  {
149  return this->Collinear(_pt, _epsilon) && this->Within(_pt, _epsilon);
150  }
151 
159  public: bool Within(const math::Vector2<T> &_pt,
160  double _epsilon = 1e-6) const
161  {
162  return _pt.X() <= std::max(this->pts[0].X(),
163  this->pts[1].X()) + _epsilon &&
164  _pt.X() >= std::min(this->pts[0].X(),
165  this->pts[1].X()) - _epsilon &&
166  _pt.Y() <= std::max(this->pts[0].Y(),
167  this->pts[1].Y()) + _epsilon &&
168  _pt.Y() >= std::min(this->pts[0].Y(),
169  this->pts[1].Y()) - _epsilon;
170  }
171 
177  public: bool Intersect(const Line2<T> &_line,
178  double _epsilon = 1e-6) const
179  {
180  static math::Vector2<T> ignore;
181  return this->Intersect(_line, ignore, _epsilon);
182  }
183 
192  public: bool Intersect(const Line2<T> &_line, math::Vector2<T> &_pt,
193  double _epsilon = 1e-6) const
194  {
195  double d = this->CrossProduct(_line);
196 
197  // d is zero if the two line are collinear. Must check special
198  // cases.
199  if (math::equal(d, 0.0, _epsilon))
200  {
201  // Check if _line's starting point is on the line.
202  if (this->Within(_line[0], _epsilon))
203  {
204  _pt = _line[0];
205  return true;
206  }
207  // Check if _line's ending point is on the line.
208  else if (this->Within(_line[1], _epsilon))
209  {
210  _pt = _line[1];
211  return true;
212  }
213  // Other wise return false.
214  else
215  return false;
216  }
217 
218  _pt.X((_line[0].X() - _line[1].X()) *
219  (this->pts[0].X() * this->pts[1].Y() -
220  this->pts[0].Y() * this->pts[1].X()) -
221  (this->pts[0].X() - this->pts[1].X()) *
222  (_line[0].X() * _line[1].Y() - _line[0].Y() * _line[1].X()));
223 
224  _pt.Y((_line[0].Y() - _line[1].Y()) *
225  (this->pts[0].X() * this->pts[1].Y() -
226  this->pts[0].Y() * this->pts[1].X()) -
227  (this->pts[0].Y() - this->pts[1].Y()) *
228  (_line[0].X() * _line[1].Y() - _line[0].Y() * _line[1].X()));
229 
230  _pt /= d;
231 
232  if (_pt.X() < std::min(this->pts[0].X(), this->pts[1].X()) ||
233  _pt.X() > std::max(this->pts[0].X(), this->pts[1].X()) ||
234  _pt.X() < std::min(_line[0].X(), _line[1].X()) ||
235  _pt.X() > std::max(_line[0].X(), _line[1].X()))
236  {
237  return false;
238  }
239 
240  if (_pt.Y() < std::min(this->pts[0].Y(), this->pts[1].Y()) ||
241  _pt.Y() > std::max(this->pts[0].Y(), this->pts[1].Y()) ||
242  _pt.Y() < std::min(_line[0].Y(), _line[1].Y()) ||
243  _pt.Y() > std::max(_line[0].Y(), _line[1].Y()))
244  {
245  return false;
246  }
247 
248  return true;
249  }
250 
253  public: T Length() const
254  {
255  return sqrt((this->pts[0].X() - this->pts[1].X()) *
256  (this->pts[0].X() - this->pts[1].X()) +
257  (this->pts[0].Y() - this->pts[1].Y()) *
258  (this->pts[0].Y() - this->pts[1].Y()));
259  }
260 
263  public: double Slope() const
264  {
265  if (math::equal(this->pts[1].X(), this->pts[0].X()))
266  return NAN_D;
267 
268  return (this->pts[1].Y() - this->pts[0].Y()) /
269  static_cast<double>(this->pts[1].X() - this->pts[0].X());
270  }
271 
275  public: bool operator==(const Line2<T> &_line) const
276  {
277  return this->pts[0] == _line[0] && this->pts[1] == _line[1];
278  }
279 
283  public: bool operator!=(const Line2<T> &_line) const
284  {
285  return !(*this == _line);
286  }
287 
291  public: math::Vector2<T> operator[](size_t _index) const
292  {
293  if (_index > 1)
294  throw IndexException();
295  return this->pts[_index];
296  }
297 
303  public: friend std::ostream &operator<<(
304  std::ostream &_out, const Line2<T> &_line)
305  {
306  _out << _line[0] << " " << _line[1];
307  return _out;
308  }
309 
310  private: math::Vector2<T> pts[2];
311  };
312 
313 
317  }
318 }
319 #endif
bool operator!=(const Line2< T > &_line) const
Inequality operator.
Definition: Line2.hh:283
Line2< float > Line2f
Definition: Line2.hh:316
static const double NAN_D
Returns the representation of a quiet not a number (NAN)
Definition: Helpers.hh:70
void Set(double _x1, double _y1, double _x2, double _y2)
Set the start and end point of the line segment.
Definition: Line2.hh:67
double CrossProduct(const Vector2< T > &_pt) const
Return the cross product of this line and the given point.
Definition: Line2.hh:92
T Y() const
Return the y value.
Definition: Vector2.hh:282
T X() const
Return the x value.
Definition: Vector2.hh:274
bool Collinear(const math::Line2< T > &_line, double _epsilon=1e-6) const
Check if the given line is collinear with this line.
Definition: Line2.hh:134
Two dimensional (x, y) vector.
Definition: Vector2.hh:29
T max(const std::vector< T > &_values)
get the maximum value of vector of values
Definition: Helpers.hh:150
T Length() const
Get the length of the line.
Definition: Line2.hh:253
A two dimensional line segment.
Definition: Line2.hh:32
bool OnSegment(const math::Vector2< T > &_pt, double _epsilon=1e-6) const
Return whether the given point is on this line segment.
Definition: Line2.hh:146
Line2(const math::Vector2< T > &_ptA, const math::Vector2< T > &_ptB)
Constructor.
Definition: Line2.hh:37
Line2< double > Line2d
Definition: Line2.hh:315
double CrossProduct(const Line2< T > &_line) const
Return the cross product of this line and the given line.
Definition: Line2.hh:79
bool Within(const math::Vector2< T > &_pt, double _epsilon=1e-6) const
Check if the given point is between the start and end points of the line segment. ...
Definition: Line2.hh:159
friend std::ostream & operator<<(std::ostream &_out, const Line2< T > &_line)
Stream extraction operator.
Definition: Line2.hh:303
double Slope() const
Get the slope of the line.
Definition: Line2.hh:263
Exception that is thrown when an out-of-bounds index is encountered.
Definition: IndexException.hh:30
bool Collinear(const math::Vector2< T > &_pt, double _epsilon=1e-6) const
Check if the given point is collinear with this line.
Definition: Line2.hh:106
Line2(double _x1, double _y1, double _x2, double _y2)
Constructor.
Definition: Line2.hh:47
bool Parallel(const math::Line2< T > &_line, double _epsilon=1e-6) const
Check if the given line is parallel with this line.
Definition: Line2.hh:120
bool Intersect(const Line2< T > &_line, double _epsilon=1e-6) const
Check if this line intersects the given line segment.
Definition: Line2.hh:177
bool operator==(const Line2< T > &_line) const
Equality operator.
Definition: Line2.hh:275
bool Intersect(const Line2< T > &_line, math::Vector2< T > &_pt, double _epsilon=1e-6) const
Check if this line intersects the given line segment.
Definition: Line2.hh:192
bool equal(const T &_a, const T &_b, const T &_epsilon=1e-6)
check if two values are equal, within a tolerance
Definition: Helpers.hh:177
T min(const std::vector< T > &_values)
get the minimum value of vector of values
Definition: Helpers.hh:163
Line2< int > Line2i
Definition: Line2.hh:314
math::Vector2< T > operator[](size_t _index) const
Get the start or end point.
Definition: Line2.hh:291
void Set(const math::Vector2< T > &_ptA, const math::Vector2< T > &_ptB)
Set the start and end point of the line segment.
Definition: Line2.hh:55