mt
 All Classes Files Functions Enumerations Groups Pages
plane3.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_PLANE3_H
25 #define MT_PLANE3_H
26 
27 // C++ STANDARD HEADERS
28 #include <iostream>
29 
30 // MT LIBRARY HEADERS
31 #include <mt/direction_type.h>
32 #include <mt/line3.h>
33 #include <mt/exception.h>
34 #include <mt/point3.h>
35 #include <mt/scalar.h>
36 #include <mt/unit3.h>
37 #include <mt/vector3.h>
38 
39 
41 
42 namespace mt
43 {
44 
45 
47 
50 
130 
131 class Plane3
132 {
133 public:
134 
136 class BadPlane : public mt::Exception
137 {
138 public:
139  BadPlane() : Exception(
140  "Ill-defined plane. Input support point is not contained in the \
141 constructed plane") {}
142 };
143 
144 
145 // LIFECYCLE
146 
149  Plane3();
150 
152  Plane3(const Unit3& norm,
153  const Scalar& dist,
154  const DirectionType& type = DIRECTED);
155 
158  Plane3(const Vector3& norm,
159  const Scalar& dist,
160  const DirectionType& type = DIRECTED);
161 
163  Plane3(const Unit3& norm,
164  const Point3& sup,
165  const DirectionType& type = DIRECTED);
166 
168  Plane3(const Vector3& norm,
169  const Point3& sup,
170  const DirectionType& type = DIRECTED);
171 
173  Plane3(const Point3& sup1,
174  const Point3& sup2,
175  const Point3& sup3,
176  const DirectionType& type = UNDIRECTED);
177 
178  // Compiler generated copy constructor is being used
179 
180  // Compiler generated destructor is being used
181 
182 
183 // OPERATORS
184 
185  // Compiler generated assignment operator is being used
186 
187  bool operator==(const Plane3& P) const;
188  bool operator!=(const Plane3& P) const;
189 
190 
191 // OPERATIONS
192 
194  Point3 project(const Point3& p) const;
195 
197  Scalar distance(const Point3& p) const;
198 
199 
200 // ACCESS
201 
203  Unit3 getNormal() const;
204  Unit3& getNormalRef();
205  const Unit3& getNormalRef() const;
206 
210  Scalar getDistOrig() const;
211  Scalar& getDistOrigRef();
212  const Scalar& getDistOrigRef() const;
213 
216  Point3 getSupport() const;
217 
219  DirectionType getDirectionType() const;
220  DirectionType& getDirectionTypeRef();
221  const DirectionType& getDirectionTypeRef() const;
222 
229  Unit3 getSupportVector() const;
230 
232  Plane3 getParallelPlane(const Scalar& d) const;
233 
235  void setNormal(const Unit3& norm);
236 
238  void setDistOrig(const Scalar& dist);
239 
241  void setSupport(const Point3& sup);
242 
244  void setDirectionType(const DirectionType& type);
245 
247  void setValue(const Unit3& norm,
248  const Scalar& dist,
249  const DirectionType& type = DIRECTED);
250 
252  void setValue(const Unit3& norm,
253  const Point3& sup,
254  const DirectionType& type = DIRECTED);
255 
257  void setValue(const Point3& sup1,
258  const Point3& sup2,
259  const Point3& sup3,
260  const DirectionType& type = DIRECTED);
261 
262 private:
263 
264 // MEMBERS
265 Unit3 m_normal;
266 Scalar m_dist_orig;
267 DirectionType m_dir_type;
268 
269 // METHODS
270 void setNormal (const Point3& sup1,
271  const Point3& sup2,
272  const Point3& sup3);
273 
274 void setSupport(const Point3& sup1,
275  const Point3& sup2,
276  const Point3& sup3);
277 
278 };
279 
281 
282 // OPERATORS
283 
284 Plane3 operator+(const Plane3& P);
285 Plane3 operator-(const Plane3& P);
286 
287 std::ostream& operator<<(std::ostream& os,
288  const Plane3& P);
289 
290 
291 // FUNCTIONS
292 
294 Point3 project(const Point3& p,
295  const Plane3& P);
296 
298 Scalar distance(const Point3& p,
299  const Plane3& P);
300 
302 Scalar distance(const Line3& L,
303  const Plane3& P);
304 
305 
307 
308 inline Plane3::Plane3() : m_normal(),
309  m_dist_orig(0.0),
310  m_dir_type(DIRECTED) {}
311 
312 
313 inline Plane3::Plane3(const Unit3& norm,
314  const Scalar& dist,
315  const DirectionType& type) :
316 
317  m_normal(norm),
318  m_dist_orig(dist),
319  m_dir_type(type) {}
320 
321 
322 inline Plane3::Plane3(const Vector3& norm,
323  const Scalar& dist,
324  const DirectionType& type) :
325 
326  m_normal(norm),
327  m_dist_orig(dist),
328  m_dir_type(type) {}
329 
330 
331 inline Plane3::Plane3(const Unit3& norm,
332  const Point3& sup,
333  const DirectionType& type) :
334 
335  m_normal(norm),
336  m_dir_type(type)
337 {
338  setSupport(sup);
339 
340  // Verifies that input point is contained in plane
341  #ifdef MT_USE_BASIC_SCALAR
342  util::Assert(distance(sup) == 0.0, BadPlane());
343  #endif
344 }
345 
346 
347 inline Plane3::Plane3(const Vector3& norm,
348  const Point3& sup,
349  const DirectionType& type) :
350 
351  m_normal(norm),
352  m_dir_type(type)
353 {
354  setSupport(sup);
355 
356  // Verifies that input point is contained in plane
357  #ifdef MT_USE_BASIC_SCALAR
358  util::Assert(distance(sup) == 0.0, BadPlane());
359  #endif
360 }
361 
362 
363 inline Plane3::Plane3(const Point3& sup1,
364  const Point3& sup2,
365  const Point3& sup3,
366  const DirectionType& type)
367 {
368  setValue(sup1, sup2, sup3, type);
369 }
370 
371 
372 // OPERATORS
373 
374 inline bool Plane3::operator==(const Plane3& P) const
375 {
376  bool equal;
377 
378  // Tests normal vector equality
379  bool same_normal = (m_normal == P.getNormal());
380 
381  // Tests distance to origin equality
382  bool same_dist_orig = (m_dist_orig == P.getDistOrig());
383 
384  if (same_normal && same_dist_orig)
385  {
386  // Planes are equal regardless of their direction type
387  equal = true;
388  }
389  else
390  {
391  // Tests if both planes are directed
392  const bool both_directed =
393  (m_dir_type == DIRECTED) && (P.getDirectionType() == DIRECTED);
394 
395  if (!both_directed)
396  {
397  // At least one of the planes is undirected
398  same_normal = (m_normal == -P.getNormal());
399  same_dist_orig = (m_dist_orig == -P.getDistOrig());
400  equal = (same_normal && same_dist_orig);
401  }
402  }
403  return equal;
404 }
405 
406 
407 inline bool Plane3::operator!=(const Plane3& P) const
408 {
409  return !(*this == P);
410 }
411 
412 
413 // OPERATIONS
414 
415 inline Point3 Plane3::project(const Point3& p) const
416 {
417  return Point3(p - (dot(p, m_normal) + m_dist_orig) * m_normal);
418 }
419 
420 
421 inline Scalar Plane3::distance(const Point3& p) const
422 {
423  return abs((dot(p, m_normal) + m_dist_orig));
424 }
425 
426 
427 // ACCESS
428 
429 inline Unit3 Plane3::getNormal() const
430 {
431  return m_normal;
432 }
433 
434 
435 inline Unit3& Plane3::getNormalRef()
436 {
437  return m_normal;
438 }
439 
440 
441 inline const Unit3& Plane3::getNormalRef() const
442 {
443  return m_normal;
444 }
445 
446 
447 inline Scalar Plane3::getDistOrig() const
448 {
449  return m_dist_orig;
450 }
451 
452 
453 inline Scalar& Plane3::getDistOrigRef()
454 {
455  return m_dist_orig;
456 }
457 
458 
459 inline const Scalar& Plane3::getDistOrigRef() const
460 {
461  return m_dist_orig;
462 }
463 
464 
466 {
467  return -(m_dist_orig * m_normal);
468 }
469 
470 
471 inline DirectionType Plane3::getDirectionType() const
472 {
473  return m_dir_type;
474 }
475 
476 
477 inline DirectionType& Plane3::getDirectionTypeRef()
478 {
479  return m_dir_type;
480 }
481 
482 
483 inline const DirectionType& Plane3::getDirectionTypeRef() const
484 {
485  return m_dir_type;
486 }
487 
488 
490 {
491  Point3 ref;
492  ref = (m_normal.closestAxis() == 0) ?
493  Point3(0.0, 1.0, 0.0) : Point3(1.0, 0.0, 0.0);
494 
495  const Point3 sup1(getSupport());
496  const Point3 sup2(project(sup1 + ref));
497 
498  const Unit3 u(sup2 - sup1);
499  return u;
500 }
501 
502 
503 inline Plane3 Plane3::getParallelPlane(const Scalar& d) const
504 {
505  const Scalar dnew = m_dist_orig - d;
506  return Plane3(m_normal, dnew, m_dir_type);
507 }
508 
509 
510 inline void Plane3::setNormal(const Unit3& norm)
511 {
512  m_normal = norm;
513 }
514 
515 
516 inline void Plane3::setDistOrig(const Scalar& dist)
517 {
518  m_dist_orig = dist;
519 }
520 
521 
522 inline void Plane3::setSupport(const Point3& sup)
523 {
524  m_dist_orig = -dot(m_normal, sup);
525 }
526 
527 
528 inline void Plane3::setDirectionType(const DirectionType& type)
529 {
530  m_dir_type = type;
531 }
532 
533 
534 inline void Plane3::setValue(const Unit3& norm,
535  const Scalar& dist,
536  const DirectionType& type)
537 {
538  setNormal(norm);
539  setDistOrig(dist);
540  setDirectionType(type);
541 }
542 
543 
544 inline void Plane3::setValue(const Unit3& norm,
545  const Point3& sup,
546  const DirectionType& type)
547 {
548  setNormal(norm);
549  setSupport(sup);
550  setDirectionType(type);
551 }
552 
553 
554 inline void Plane3::setValue(const Point3& sup1,
555  const Point3& sup2,
556  const Point3& sup3,
557  const DirectionType& type)
558 {
559  // Sets normal
560  setNormal(sup1, sup2, sup3);
561 
562  // Sets support point
563  setSupport(sup1, sup2, sup3);
564 
565  // Sets direction type
566  setDirectionType(type);
567 }
568 
569 
570 // PROTECTED METHODS
571 
572 inline void Plane3::setNormal(const Point3& sup1,
573  const Point3& sup2,
574  const Point3& sup3)
575 {
576  // Tests that input points are not collinear
577  const Unit3 dir[3] = {(sup2 - sup1),
578  (sup3 - sup2),
579  (sup1 - sup3)};
580 
581  const Vector3 cos_vec(abs(angleCos(dir[0], dir[1])),
582  abs(angleCos(dir[1], dir[2])),
583  abs(angleCos(dir[2], dir[0])));
584 
585  const Scalar max_cos = cos_vec.max();
586 
587  #ifdef MT_USE_BASIC_SCALAR
588  util::Assert(max_cos != 1.0,
589  Exception("Ill-defined plane. Input points are collinear"));
590  #endif
591 
592  // Sets normal vector with support unit vectors that lie at an angle with
593  // value closest to pi/2
594  const size_t min_cos_idx = cos_vec.minAxis();
595  const size_t t1 = ( min_cos_idx % 3) + 1;
596  const size_t t2 = ((min_cos_idx + 1) % 3) + 1;
597  m_normal = cross(dir[t1], dir[t2]);
598 }
599 
600 
601 inline void Plane3::setSupport(const Point3& sup1,
602  const Point3& sup2,
603  const Point3& sup3)
604 {
605  // Sets point closest to the origin as support point
606  const Point3 p[3] = {sup1,
607  sup2,
608  sup3};
609 
610  const Vector3 len_p (p[0].length2(),
611  p[1].length2(),
612  p[2].length2());
613 
614  const size_t t = len_p.minAxis();
615  setSupport(p[t]);
616 
617  // Verifies that input points are contained in plane
618  #ifdef MT_USE_BASIC_SCALAR
619  util::Assert(distance(sup1) == 0.0, BadPlane());
620  util::Assert(distance(sup2) == 0.0, BadPlane());
621  util::Assert(distance(sup3) == 0.0, BadPlane());
622  #endif
623 }
624 
625 
627 
628 // OPERATORS
629 
630 inline Plane3 operator+(const Plane3& P)
631 {
632  return P;
633 }
634 
635 
636 inline Plane3 operator-(const Plane3& P)
637 {
638  return Plane3(-P.getNormal(),
639  P.getDistOrig(),
640  P.getDirectionType());
641 }
642 
643 
644 inline std::ostream& operator<<(std::ostream& os,
645  const Plane3& P)
646 {
647  return os << "norm: " << P.getNormal() << ' '
648  << "dist: " << P.getDistOrig() << " - "
649  << P.getDirectionType();
650 }
651 
652 
653 // FUNCTIONS
654 
655 inline Point3 project(const Point3& p,
656  const Plane3& P)
657 {
658  return P.project(p);
659 }
660 
661 
662 inline Scalar distance(const Point3& p,
663  const Plane3& P)
664 {
665  return P.distance(p);
666 }
667 
668 
669 inline Scalar distance(const Plane3& P,
670  const Point3& p)
671 {
672  return P.distance(p);
673 }
674 
675 
676 } // mt
677 
678 #endif // MT_PLANE3_H