mt
 All Classes Files Functions Enumerations Groups Pages
line3.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2006 by Adolfo Rodriguez *
3  * adolfo.rodriguez@upc.edu *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
22 
23 // HEADER GUARD
24 #ifndef MT_LINE3_H
25 #define MT_LINE3_H
26 
27 // C++ STANDARD HEADERS
28 #include <iostream>
29 
30 // MT LIBRARY HEADERS
31 #include <mt/direction_type.h>
32 #include <mt/exception.h>
33 #include <mt/point3.h>
34 #include <mt/scalar.h>
35 #include <mt/unit3.h>
36 #include <mt/vector3.h>
37 
38 
40 
41 namespace mt
42 {
43 
44 
46 
49 
131 
132 class Line3
133 {
134 public:
135 
137 class BadLine : public Exception
138 {
139 public:
140  BadLine() : Exception(
141  "Ill-defined line. Input support point is not contained in the constructed \
142 line") {}
143 };
144 
145 
146 // LIFECYCLE
147 
150  Line3();
151 
152 
154  Line3(const Unit3& dir,
155  const Point3& sup,
156  const DirectionType& type = DIRECTED);
157 
159  Line3(const Vector3& dir,
160  const Point3& sup,
161  const DirectionType& type = DIRECTED);
162 
164  Line3(const Point3& sup1,
165  const Point3& sup2,
166  const DirectionType& type = DIRECTED);
167 
168  // Compiler generated copy constructor is being used
169 
170  // Compiler generated destructor is being used
171 
172 
173 // OPERATORS
174 
175  // Compiler generated assignment operator is being used
176 
177  bool operator==(const Line3& L) const;
178  bool operator!=(const Line3& L) const;
179 
180 // OPERATIONS
181 
183  Point3 project(const Point3& p) const;
184 
186  Scalar distance(const Point3& p) const;
187 
188 
189 // ACCESS
190 
192  Unit3 getDirection() const;
193  Unit3& getDirectionRef();
194  const Unit3& getDirectionRef() const;
195 
198  Point3 getSupport() const;
199  Point3& getSupportRef();
200  const Point3& getSupportRef() const;
201 
203  DirectionType getDirectionType() const;
204  DirectionType& getDirectionTypeRef();
205  const DirectionType& getDirectionTypeRef() const;
206 
209  Point3 getPoint(const Scalar& t) const;
210 
212  Scalar getParameter(const Point3& p) const;
213 
215  void setDirection(const Unit3& dir);
216 
218  void setSupport(const Point3& sup);
219 
221  void setDirectionType(const DirectionType& type);
222 
224  void setValue(const Unit3& dir,
225  const Point3& sup,
226  const DirectionType& type = DIRECTED);
227 
228 
229 private:
230 
231 // MEMBERS
232 Unit3 m_direction;
233 Point3 m_support;
234 DirectionType m_dir_type;
235 
236 };
237 
239 
240 // OPERATORS
241 
242 Line3 operator+(const Line3& L);
243 Line3 operator-(const Line3& L);
244 
245 std::ostream& operator<<(std::ostream& os,
246  const Line3& L);
247 
248 
249 // FUNCTIONS
250 
252 Point3 project(const Point3& p,
253  const Line3& L);
254 
256 Scalar distance(const Point3& p,
257  const Line3& L);
258 
260 Scalar distance(const Line3& L,
261  const Point3& p);
262 
263 
264 
266 
267 // LIFECYCLE
268 
269 inline Line3::Line3() : m_direction(),
270  m_support(),
271  m_dir_type(DIRECTED) {}
272 
273 
274 inline Line3::Line3(const Unit3& dir,
275  const Point3& sup,
276  const DirectionType& type) :
277 
278  m_direction(dir),
279  m_dir_type(type)
280 {
281  setSupport(sup);
282 
283  // Verifies that input point is contained in line
284  #ifdef MT_USE_BASIC_SCALAR
285  util::Assert(distance(sup) == 0.0, BadLine());
286  #endif
287 }
288 
289 
290 inline Line3::Line3(const Vector3& dir,
291  const Point3& sup,
292  const DirectionType& type) :
293 
294  m_direction(dir),
295  m_dir_type(type)
296 {
297  setSupport(sup);
298 
299  // Verifies that input point is contained in line
300  #ifdef MT_USE_BASIC_SCALAR
301  util::Assert(distance(sup) == 0.0, BadLine());
302  #endif
303 }
304 
305 
306 inline Line3::Line3(const Point3& sup1,
307  const Point3& sup2,
308  const DirectionType& type) :
309 
310  m_dir_type(type)
311 {
312  // Verifies that the input points are not coincident
313  #ifdef MT_USE_BASIC_SCALAR
314  util::Assert(mt::distance(sup1, sup2) != 0.0,
315  Exception("Cannot define line with two coincident points."));
316  #endif
317 
318  // Point that is closest to the origin of the current coordinate system
319  const Point3 p_closest = (sup1.length() < sup2.length()) ? sup1 : sup2;
320 
321  // Sets remaining line parameters
322  setDirection(sup2 - sup1);
323  setSupport(p_closest);
324 
325  // Verifies that input points are contained in line
326  #ifdef MT_USE_BASIC_SCALAR
327  util::Assert(distance(sup1) == 0.0, BadLine());
328  util::Assert(distance(sup2) == 0.0, BadLine());
329  #endif
330 }
331 
332 // OPERATORS
333 
334 inline bool Line3::operator==(const Line3& L) const
335 {
336  // Tests direction vector equality
337  bool same_direction = (m_direction == L.getDirection());
338 
339  // Tests support point equality
340  const bool same_support = (m_support == L.getSupport());
341 
342  // Tests if both lines are directed
343  const bool both_directed =
344  (m_dir_type == DIRECTED) && (L.getDirectionType() == DIRECTED);
345 
346  if (!both_directed)
347  {
348  // At least one of the lines is undirected
349  const bool opposite_direction = (m_direction == -L.getDirection());
350  same_direction |= opposite_direction;
351  }
352  return (same_support && same_direction);
353 }
354 
355 inline bool Line3::operator!=(const Line3& L) const
356 {
357  return !(*this == L);
358 }
359 
360 
361 // ACCESS
362 
363 
365 {
366  return m_direction;
367 }
368 
369 
370 inline Unit3& Line3::getDirectionRef()
371 {
372  return m_direction;
373 }
374 
375 
376 inline const Unit3& Line3::getDirectionRef() const
377 {
378  return m_direction;
379 }
380 
381 
382 inline Point3 Line3::getSupport() const
383 {
384  return m_support;
385 }
386 
387 
388 inline Point3& Line3::getSupportRef()
389 {
390  return m_support;
391 }
392 
393 
394 inline const Point3& Line3::getSupportRef() const
395 {
396  return m_support;
397 }
398 
399 
400 inline DirectionType Line3::getDirectionType() const
401 {
402  return m_dir_type;
403 }
404 
405 
406 inline DirectionType& Line3::getDirectionTypeRef()
407 {
408  return m_dir_type;
409 }
410 
411 
412 inline const DirectionType& Line3::getDirectionTypeRef() const
413 {
414  return m_dir_type;
415 }
416 
417 
418 inline Point3 Line3::getPoint(const Scalar& t) const
419 {
420  return Point3(m_support + t * m_direction);
421 }
422 
423 
424 inline Scalar Line3::getParameter(const Point3& p) const
425 {
426  // Component of direction vector with highest absolute value
427  const size_t i = m_direction.closestAxis();
428 
429  // Parameter value
430  return (p[i] - m_support[i]) / m_direction[i];
431 }
432 
433 
434 inline void Line3::setDirection(const Unit3& dir)
435 {
436  m_direction = dir;
437 }
438 
439 
440 inline void Line3::setSupport(const Point3& sup)
441 {
442  const Point3 origin(0.0, 0.0, 0.0);
443  m_support = sup;
444  m_support = project(origin);
445 }
446 
447 
448 inline void Line3::setDirectionType(const DirectionType& type)
449 {
450  m_dir_type = type;
451 }
452 
453 
454 inline void Line3::setValue(const Unit3& dir,
455  const Point3& sup,
456  const DirectionType& type)
457 {
458  setDirection(dir);
459  setSupport(sup);
460  setDirectionType(type);
461 }
462 
463 // OPERATIONS
464 
465 inline Point3 Line3::project(const Point3& p) const
466 {
467  const Point3 diff(p - m_support);
468  const Scalar t = dot(diff, m_direction);
469  return getPoint(t);
470 }
471 
472 
473 inline Scalar Line3::distance(const Point3& p) const
474 {
475  const Vector3 diff(p - project(p));
476  return length(diff);
477 }
478 
479 
481 
482 // OPERATORS
483 
484 inline Line3 operator+(const Line3& L)
485 {
486  return L;
487 }
488 
489 
490 inline Line3 operator-(const Line3& L)
491 {
492  return Line3(-L.getDirection(),
493  L.getSupport(),
494  L.getDirectionType());
495 }
496 
497 
498 inline std::ostream& operator<<(std::ostream& os,
499  const Line3& L)
500 {
501  return os << "dir: " << L.getDirection() << ' '
502  << "sup: " << L.getSupport() << " - "
503  << L.getDirectionType();
504 
505 }
506 
507 // FUNCTIONS
508 
509 inline Point3 project(const Point3& p,
510  const Line3& L)
511 {
512  return L.project(p);
513 }
514 
515 
516 inline Scalar distance(const Point3& p,
517  const Line3& L)
518 {
519  return L.distance(p);
520 }
521 
522 
523 inline Scalar distance(const Line3& L,
524  const Point3& p)
525 {
526  return L.distance(p);
527 }
528 
529 
530 } // mt
531 
532 #endif // MT_LINE3_H