Ignition Math

API Reference

5.1.0
Line3.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 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_MATH_LINE3_HH_
18 #define IGNITION_MATH_LINE3_HH_
19 
20 #include <algorithm>
21 #include <ignition/math/Vector3.hh>
22 #include <ignition/math/config.hh>
23 
24 namespace ignition
25 {
26  namespace math
27  {
28  // Inline bracket to help doxygen filtering.
29  inline namespace IGNITION_MATH_VERSION_NAMESPACE {
30  //
34  template<typename T>
35  class Line3
36  {
38  public: Line3() = default;
39 
42  public: Line3(const Line3<T> &_line)
43  {
44  this->pts[0] = _line[0];
45  this->pts[1] = _line[1];
46  }
47 
51  public: Line3(const math::Vector3<T> &_ptA, const math::Vector3<T> &_ptB)
52  {
53  this->Set(_ptA, _ptB);
54  }
55 
61  public: Line3(const double _x1, const double _y1,
62  const double _x2, const double _y2)
63  {
64  this->Set(_x1, _y1, _x2, _y2);
65  }
66 
74  public: Line3(const double _x1, const double _y1,
75  const double _z1, const double _x2,
76  const double _y2, const double _z2)
77  {
78  this->Set(_x1, _y1, _z1, _x2, _y2, _z2);
79  }
80 
84  public: void Set(const math::Vector3<T> &_ptA,
85  const math::Vector3<T> &_ptB)
86  {
87  this->pts[0] = _ptA;
88  this->pts[1] = _ptB;
89  }
90 
93  public: void SetA(const math::Vector3<T> &_ptA)
94  {
95  this->pts[0] = _ptA;
96  }
97 
100  public: void SetB(const math::Vector3<T> &_ptB)
101  {
102  this->pts[1] = _ptB;
103  }
104 
113  public: void Set(const double _x1, const double _y1,
114  const double _x2, const double _y2,
115  const double _z = 0)
116  {
117  this->pts[0].Set(_x1, _y1, _z);
118  this->pts[1].Set(_x2, _y2, _z);
119  }
120 
128  public: void Set(const double _x1, const double _y1,
129  const double _z1, const double _x2,
130  const double _y2, const double _z2)
131  {
132  this->pts[0].Set(_x1, _y1, _z1);
133  this->pts[1].Set(_x2, _y2, _z2);
134  }
135 
138  public: math::Vector3<T> Direction() const
139  {
140  return (this->pts[1] - this->pts[0]).Normalize();
141  }
142 
145  public: T Length() const
146  {
147  return this->pts[0].Distance(this->pts[1]);
148  }
149 
159  public: bool Distance(const Line3<T> &_line, Line3<T> &_result,
160  const double _epsilon = 1e-6) const
161  {
162  Vector3<T> p13 = this->pts[0] - _line[0];
163  Vector3<T> p43 = _line[1] - _line[0];
164 
165  if (std::abs(p43.X()) < _epsilon && std::abs(p43.Y()) < _epsilon &&
166  std::abs(p43.Z()) < _epsilon)
167  {
168  return false;
169  }
170 
171  Vector3<T> p21 = this->pts[1] - this->pts[0];
172 
173  if (std::abs(p21.X()) < _epsilon && std::abs(p21.Y()) < _epsilon &&
174  std::abs(p21.Z()) < _epsilon)
175  {
176  return false;
177  }
178 
179  double d1343 = p13.Dot(p43);
180  double d4321 = p43.Dot(p21);
181  double d1321 = p13.Dot(p21);
182  double d4343 = p43.Dot(p43);
183  double d2121 = p21.Dot(p21);
184 
185  double denom = d2121 * d4343 - d4321 * d4321;
186 
187  // In this case, we choose the first point in this line,
188  // and the closest point in the provided line.
189  if (std::abs(denom) < _epsilon)
190  {
191  double d1 = this->pts[0].Distance(_line[0]);
192  double d2 = this->pts[0].Distance(_line[1]);
193 
194  double d3 = this->pts[1].Distance(_line[0]);
195  double d4 = this->pts[1].Distance(_line[1]);
196 
197  if (d1 <= d2 && d1 <= d3 && d1 <= d4)
198  {
199  _result.SetA(this->pts[0]);
200  _result.SetB(_line[0]);
201  }
202  else if (d2 <= d3 && d2 <= d4)
203  {
204  _result.SetA(this->pts[0]);
205  _result.SetB(_line[1]);
206  }
207  else if (d3 <= d4)
208  {
209  _result.SetA(this->pts[1]);
210  _result.SetB(_line[0]);
211  }
212  else
213  {
214  _result.SetA(this->pts[1]);
215  _result.SetB(_line[1]);
216  }
217 
218  return true;
219  }
220 
221  double numer = d1343 * d4321 - d1321 * d4343;
222 
223  double mua = clamp(numer / denom, 0.0, 1.0);
224  double mub = clamp((d1343 + d4321 * mua) / d4343, 0.0, 1.0);
225 
226  _result.Set(this->pts[0] + (p21 * mua), _line[0] + (p43 * mub));
227 
228  return true;
229  }
230 
236  public: bool Intersect(const Line3<T> &_line,
237  double _epsilon = 1e-6) const
238  {
239  static math::Vector3<T> ignore;
240  return this->Intersect(_line, ignore, _epsilon);
241  }
242 
248  public: bool Coplanar(const Line3<T> &_line,
249  const double _epsilon = 1e-6) const
250  {
251  return std::abs((_line[0] - this->pts[0]).Dot(
252  (this->pts[1] - this->pts[0]).Cross(_line[1] - _line[0])))
253  <= _epsilon;
254  }
255 
261  public: bool Parallel(const Line3<T> &_line,
262  const double _epsilon = 1e-6) const
263  {
264  return (this->pts[1] - this->pts[0]).Cross(
265  _line[1] - _line[0]).Length() <= _epsilon;
266  }
267 
276  public: bool Intersect(const Line3<T> &_line, math::Vector3<T> &_pt,
277  double _epsilon = 1e-6) const
278  {
279  // Handle special case when lines are parallel
280  if (this->Parallel(_line, _epsilon))
281  {
282  // Check if _line's starting point is on the line.
283  if (this->Within(_line[0], _epsilon))
284  {
285  _pt = _line[0];
286  return true;
287  }
288  // Check if _line's ending point is on the line.
289  else if (this->Within(_line[1], _epsilon))
290  {
291  _pt = _line[1];
292  return true;
293  }
294  // Otherwise return false.
295  else
296  return false;
297  }
298 
299  // Get the line that is the shortest distance between this and _line
300  math::Line3<T> distLine;
301  this->Distance(_line, distLine, _epsilon);
302 
303  // If the length of the line is less than epsilon, then they
304  // intersect.
305  if (distLine.Length() < _epsilon)
306  {
307  _pt = distLine[0];
308  return true;
309  }
310 
311  return false;
312  }
313 
320  public: bool Within(const math::Vector3<T> &_pt,
321  double _epsilon = 1e-6) const
322  {
323  return _pt.X() <= std::max(this->pts[0].X(),
324  this->pts[1].X()) + _epsilon &&
325  _pt.X() >= std::min(this->pts[0].X(),
326  this->pts[1].X()) - _epsilon &&
327  _pt.Y() <= std::max(this->pts[0].Y(),
328  this->pts[1].Y()) + _epsilon &&
329  _pt.Y() >= std::min(this->pts[0].Y(),
330  this->pts[1].Y()) - _epsilon &&
331  _pt.Z() <= std::max(this->pts[0].Z(),
332  this->pts[1].Z()) + _epsilon &&
333  _pt.Z() >= std::min(this->pts[0].Z(),
334  this->pts[1].Z()) - _epsilon;
335  }
336 
340  public: bool operator==(const Line3<T> &_line) const
341  {
342  return this->pts[0] == _line[0] && this->pts[1] == _line[1];
343  }
344 
348  public: bool operator!=(const Line3<T> &_line) const
349  {
350  return !(*this == _line);
351  }
352 
356  public: math::Vector3<T> operator[](const size_t _index) const
357  {
358  return this->pts[clamp(_index, IGN_ZERO_SIZE_T, IGN_ONE_SIZE_T)];
359  }
360 
365  public: friend std::ostream &operator<<(
366  std::ostream &_out, const Line3<T> &_line)
367  {
368  _out << _line[0] << " " << _line[1];
369  return _out;
370  }
371 
375  public: Line3 &operator=(const Line3<T> &_line)
376  {
377  this->pts[0] = _line[0];
378  this->pts[1] = _line[1];
379 
380  return *this;
381  }
382 
384  private: math::Vector3<T> pts[2];
385  };
386 
390  }
391  }
392 }
393 #endif
Line3< double > Line3d
Definition: Line3.hh:388
bool Within(const math::Vector3< T > &_pt, double _epsilon=1e-6) const
Check if the given point is between the start and end points of the line segment. ...
Definition: Line3.hh:320
bool operator!=(const Line3< T > &_line) const
Inequality operator.
Definition: Line3.hh:348
Line3(const double _x1, const double _y1, const double _z1, const double _x2, const double _y2, const double _z2)
Constructor.
Definition: Line3.hh:74
void Set(const double _x1, const double _y1, const double _x2, const double _y2, const double _z=0)
Set the start and end point of the line segment, assuming that both points have the same height...
Definition: Line3.hh:113
static const static double const static double const static double const static double const static float const static float const static float const static float const static uint16_t const static uint16_t const static uint16_t const static uint16_t const static int16_t const static int16_t const static int16_t const static int16_t const static uint32_t const static uint32_t const static uint32_t const static uint32_t const static int32_t const static int32_t const static int32_t const static int32_t const static uint64_t const static uint64_t const static uint64_t const static uint64_t const static int64_t const static int64_t const static int64_t const int64_t T clamp(T _v, T _min, T _max)
Simple clamping function.
Definition: Helpers.hh:402
Line3(const double _x1, const double _y1, const double _x2, const double _y2)
2D Constructor where Z coordinates are 0
Definition: Line3.hh:61
void Set(const math::Vector3< T > &_ptA, const math::Vector3< T > &_ptB)
Set the start and end point of the line segment.
Definition: Line3.hh:84
static const size_t IGN_ONE_SIZE_T
size_t type with a value of 1
Definition: Helpers.hh:226
T X() const
Get the x value.
Definition: Vector3.hh:648
friend std::ostream & operator<<(std::ostream &_out, const Line3< T > &_line)
Stream extraction operator.
Definition: Line3.hh:365
T Z() const
Get the z value.
Definition: Vector3.hh:662
T min(T... args)
T Y() const
Get the y value.
Definition: Vector3.hh:655
Line3(const Line3< T > &_line)
Copy constructor.
Definition: Line3.hh:42
void SetA(const math::Vector3< T > &_ptA)
Set the start point of the line segment.
Definition: Line3.hh:93
Line3(const math::Vector3< T > &_ptA, const math::Vector3< T > &_ptB)
Constructor.
Definition: Line3.hh:51
T Dot(const Vector3< T > &_v) const
Return the dot product of this vector and another vector.
Definition: Vector3.hh:199
static const size_t IGN_ZERO_SIZE_T
size_t type with a value of 0
Definition: Helpers.hh:223
void SetB(const math::Vector3< T > &_ptB)
Set the end point of the line segment.
Definition: Line3.hh:100
bool Intersect(const Line3< T > &_line, math::Vector3< T > &_pt, double _epsilon=1e-6) const
Check if this line intersects the given line segment. The point of intersection is returned in the _p...
Definition: Line3.hh:276
T max(T... args)
bool Parallel(const Line3< T > &_line, const double _epsilon=1e-6) const
Test if this line and the given line are parallel.
Definition: Line3.hh:261
Line3< int > Line3i
Definition: Line3.hh:387
bool operator==(const Line3< T > &_line) const
Equality operator.
Definition: Line3.hh:340
math::Vector3< T > operator[](const size_t _index) const
Get the start or end point.
Definition: Line3.hh:356
The Vector3 class represents the generic vector containing 3 elements. Since it&#39;s commonly used to ke...
Definition: Vector3.hh:40
math::Vector3< T > Direction() const
Get the direction of the line.
Definition: Line3.hh:138
Line3 & operator=(const Line3< T > &_line)
Assignment operator.
Definition: Line3.hh:375
Line3< float > Line3f
Definition: Line3.hh:389
bool Coplanar(const Line3< T > &_line, const double _epsilon=1e-6) const
Test if this line and the given line are coplanar.
Definition: Line3.hh:248
A three dimensional line segment. The line is defined by a start and end point.
Definition: Line3.hh:35
T Length() const
Get the length of the line.
Definition: Line3.hh:145
Definition: Angle.hh:39
STL class.
void Set(const double _x1, const double _y1, const double _z1, const double _x2, const double _y2, const double _z2)
Set the start and end point of the line segment.
Definition: Line3.hh:128
bool Distance(const Line3< T > &_line, Line3< T > &_result, const double _epsilon=1e-6) const
Get the shortest line between this line and the provided line.
Definition: Line3.hh:159
bool Intersect(const Line3< T > &_line, double _epsilon=1e-6) const
Check if this line intersects the given line segment.
Definition: Line3.hh:236