Ignition Math

API Reference

6.4.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 
160  public: bool Distance(const Line3<T> &_line, Line3<T> &_result,
161  const double _epsilon = 1e-6) const
162  {
163  Vector3<T> p13 = this->pts[0] - _line[0];
164  Vector3<T> p43 = _line[1] - _line[0];
165 
166  if (std::abs(p43.X()) < _epsilon && std::abs(p43.Y()) < _epsilon &&
167  std::abs(p43.Z()) < _epsilon)
168  {
169  return false;
170  }
171 
172  Vector3<T> p21 = this->pts[1] - this->pts[0];
173 
174  if (std::abs(p21.X()) < _epsilon && std::abs(p21.Y()) < _epsilon &&
175  std::abs(p21.Z()) < _epsilon)
176  {
177  return false;
178  }
179 
180  double d1343 = p13.Dot(p43);
181  double d4321 = p43.Dot(p21);
182  double d1321 = p13.Dot(p21);
183  double d4343 = p43.Dot(p43);
184  double d2121 = p21.Dot(p21);
185 
186  double denom = d2121 * d4343 - d4321 * d4321;
187 
188  // In this case, we choose the first point in this line,
189  // and the closest point in the provided line.
190  if (std::abs(denom) < _epsilon)
191  {
192  double d1 = this->pts[0].Distance(_line[0]);
193  double d2 = this->pts[0].Distance(_line[1]);
194 
195  double d3 = this->pts[1].Distance(_line[0]);
196  double d4 = this->pts[1].Distance(_line[1]);
197 
198  if (d1 <= d2 && d1 <= d3 && d1 <= d4)
199  {
200  _result.SetA(this->pts[0]);
201  _result.SetB(_line[0]);
202  }
203  else if (d2 <= d3 && d2 <= d4)
204  {
205  _result.SetA(this->pts[0]);
206  _result.SetB(_line[1]);
207  }
208  else if (d3 <= d4)
209  {
210  _result.SetA(this->pts[1]);
211  _result.SetB(_line[0]);
212  }
213  else
214  {
215  _result.SetA(this->pts[1]);
216  _result.SetB(_line[1]);
217  }
218 
219  return true;
220  }
221 
222  double numer = d1343 * d4321 - d1321 * d4343;
223 
224  double mua = clamp(numer / denom, 0.0, 1.0);
225  double mub = clamp((d1343 + d4321 * mua) / d4343, 0.0, 1.0);
226 
227  _result.Set(this->pts[0] + (p21 * mua), _line[0] + (p43 * mub));
228 
229  return true;
230  }
231 
237  public: bool Intersect(const Line3<T> &_line,
238  double _epsilon = 1e-6) const
239  {
240  static math::Vector3<T> ignore;
241  return this->Intersect(_line, ignore, _epsilon);
242  }
243 
249  public: bool Coplanar(const Line3<T> &_line,
250  const double _epsilon = 1e-6) const
251  {
252  return std::abs((_line[0] - this->pts[0]).Dot(
253  (this->pts[1] - this->pts[0]).Cross(_line[1] - _line[0])))
254  <= _epsilon;
255  }
256 
262  public: bool Parallel(const Line3<T> &_line,
263  const double _epsilon = 1e-6) const
264  {
265  return (this->pts[1] - this->pts[0]).Cross(
266  _line[1] - _line[0]).Length() <= _epsilon;
267  }
268 
277  public: bool Intersect(const Line3<T> &_line, math::Vector3<T> &_pt,
278  double _epsilon = 1e-6) const
279  {
280  // Handle special case when lines are parallel
281  if (this->Parallel(_line, _epsilon))
282  {
283  // Check if _line's starting point is on the line.
284  if (this->Within(_line[0], _epsilon))
285  {
286  _pt = _line[0];
287  return true;
288  }
289  // Check if _line's ending point is on the line.
290  else if (this->Within(_line[1], _epsilon))
291  {
292  _pt = _line[1];
293  return true;
294  }
295  // Otherwise return false.
296  else
297  return false;
298  }
299 
300  // Get the line that is the shortest distance between this and _line
301  math::Line3<T> distLine;
302  this->Distance(_line, distLine, _epsilon);
303 
304  // If the length of the line is less than epsilon, then they
305  // intersect.
306  if (distLine.Length() < _epsilon)
307  {
308  _pt = distLine[0];
309  return true;
310  }
311 
312  return false;
313  }
314 
321  public: bool Within(const math::Vector3<T> &_pt,
322  double _epsilon = 1e-6) const
323  {
324  return _pt.X() <= std::max(this->pts[0].X(),
325  this->pts[1].X()) + _epsilon &&
326  _pt.X() >= std::min(this->pts[0].X(),
327  this->pts[1].X()) - _epsilon &&
328  _pt.Y() <= std::max(this->pts[0].Y(),
329  this->pts[1].Y()) + _epsilon &&
330  _pt.Y() >= std::min(this->pts[0].Y(),
331  this->pts[1].Y()) - _epsilon &&
332  _pt.Z() <= std::max(this->pts[0].Z(),
333  this->pts[1].Z()) + _epsilon &&
334  _pt.Z() >= std::min(this->pts[0].Z(),
335  this->pts[1].Z()) - _epsilon;
336  }
337 
341  public: bool operator==(const Line3<T> &_line) const
342  {
343  return this->pts[0] == _line[0] && this->pts[1] == _line[1];
344  }
345 
349  public: bool operator!=(const Line3<T> &_line) const
350  {
351  return !(*this == _line);
352  }
353 
357  public: math::Vector3<T> operator[](const size_t _index) const
358  {
359  return this->pts[clamp(_index, IGN_ZERO_SIZE_T, IGN_ONE_SIZE_T)];
360  }
361 
366  public: friend std::ostream &operator<<(
367  std::ostream &_out, const Line3<T> &_line)
368  {
369  _out << _line[0] << " " << _line[1];
370  return _out;
371  }
372 
376  public: Line3 &operator=(const Line3<T> &_line)
377  {
378  this->pts[0] = _line[0];
379  this->pts[1] = _line[1];
380 
381  return *this;
382  }
383 
385  private: math::Vector3<T> pts[2];
386  };
387 
391  }
392  }
393 }
394 #endif
Line3< double > Line3d
Definition: Line3.hh:389
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:321
bool operator!=(const Line3< T > &_line) const
Inequality operator.
Definition: Line3.hh:349
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
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:229
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:366
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:226
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:277
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:262
Line3< int > Line3i
Definition: Line3.hh:388
bool operator==(const Line3< T > &_line) const
Equality operator.
Definition: Line3.hh:341
math::Vector3< T > operator[](const size_t _index) const
Get the start or end point.
Definition: Line3.hh:357
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:376
Line3< float > Line3f
Definition: Line3.hh:390
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:249
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:42
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:160
T clamp(T _v, T _min, T _max)
Simple clamping function.
Definition: Helpers.hh:405
bool Intersect(const Line3< T > &_line, double _epsilon=1e-6) const
Check if this line intersects the given line segment.
Definition: Line3.hh:237