WFMath  1.0.1
rotbox.h
1 // rotbox.h (A box with arbitrary orientation)
2 //
3 // The WorldForge Project
4 // Copyright (C) 2000, 2001 The WorldForge Project
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //
20 // For information about WorldForge and its authors, please contact
21 // the Worldforge Web Site at http://www.worldforge.org.
22 //
23 
24 // Author: Ron Steinke
25 
26 #ifndef WFMATH_ROT_BOX_H
27 #define WFMATH_ROT_BOX_H
28 
29 #include <wfmath/point.h>
30 #include <wfmath/rotmatrix.h>
31 #include <wfmath/intersect_decls.h>
32 
33 namespace WFMath {
34 
35 template<int dim>
36 std::ostream& operator<<(std::ostream& os, const RotBox<dim>& r);
37 template<int dim>
38 std::istream& operator>>(std::istream& is, RotBox<dim>& r);
39 
41 
45 template<int dim = 3>
46 class RotBox
47 {
48  public:
50  RotBox() : m_corner0(), m_size(), m_orient() {}
52 
57  RotBox(const Point<dim>& p, const Vector<dim>& size,
58  const RotMatrix<dim>& orientation) : m_corner0(p), m_size(size),
59  m_orient(orientation) {}
61  RotBox(const RotBox& b) : m_corner0(b.m_corner0), m_size(b.m_size),
62  m_orient(b.m_orient) {}
64  explicit RotBox(const AtlasInType& a);
65 
66  ~RotBox() {}
67 
69  AtlasOutType toAtlas() const;
71  void fromAtlas(const AtlasInType& a);
72 
73  friend std::ostream& operator<< <dim>(std::ostream& os, const RotBox& r);
74  friend std::istream& operator>> <dim>(std::istream& is, RotBox& r);
75 
76  RotBox& operator=(const RotBox& s);
77 
78  bool isEqualTo(const RotBox& b, CoordType epsilon = numeric_constants<CoordType>::epsilon()) const;
79 
80  bool operator==(const RotBox& b) const {return isEqualTo(b);}
81  bool operator!=(const RotBox& b) const {return !isEqualTo(b);}
82 
83  bool isValid() const {return m_corner0.isValid() && m_size.isValid()
84  && m_orient.isValid();}
85 
86  // Descriptive characteristics
87 
88  size_t numCorners() const {return 1 << dim;}
89  Point<dim> getCorner(size_t i) const;
90  Point<dim> getCenter() const {return m_corner0 + Prod(m_size / 2, m_orient);}
91 
93  const Point<dim>& corner0() const {return m_corner0;}
95  Point<dim>& corner0() {return m_corner0;}
97  const Vector<dim>& size() const {return m_size;}
99  Vector<dim>& size() {return m_size;}
101  const RotMatrix<dim>& orientation() const {return m_orient;}
103  RotMatrix<dim>& orientation() {return m_orient;}
104 
105  // Movement functions
106 
107  RotBox& shift(const Vector<dim>& v)
108  {m_corner0 += v; return *this;}
109  RotBox& moveCornerTo(const Point<dim>& p, size_t corner)
110  {return shift(p - getCorner(corner));}
111  RotBox& moveCenterTo(const Point<dim>& p)
112  {return shift(p - getCenter());}
113 
114  RotBox& rotateCorner(const RotMatrix<dim>& m, size_t corner)
115  {rotatePoint(m, getCorner(corner)); return *this;}
116  RotBox& rotateCenter(const RotMatrix<dim>& m)
117  {rotatePoint(m, getCenter()); return *this;}
118  RotBox& rotatePoint(const RotMatrix<dim>& m, const Point<dim>& p)
119  {m_orient = Prod(m_orient, m); m_corner0.rotate(m, p); return *this;}
120 
121  // 3D rotation functions
122  RotBox& rotateCorner(const Quaternion& q, size_t corner);
123  RotBox& rotateCenter(const Quaternion& q);
124  RotBox& rotatePoint(const Quaternion& q, const Point<dim>& p);
125 
126  // Intersection functions
127 
128  AxisBox<dim> boundingBox() const;
129  Ball<dim> boundingSphere() const
130  {return Ball<dim>(getCenter(), m_size.mag() / 2);}
131  Ball<dim> boundingSphereSloppy() const
132  {return Ball<dim>(getCenter(), m_size.sqrMag() / 2);}
133 
134  RotBox toParentCoords(const Point<dim>& origin,
135  const RotMatrix<dim>& rotation = RotMatrix<dim>().identity()) const
136  {return RotBox(m_corner0.toParentCoords(origin, rotation), m_size,
137  m_orient * rotation);}
138  RotBox toParentCoords(const AxisBox<dim>& coords) const
139  {return RotBox(m_corner0.toParentCoords(coords), m_size, m_orient);}
140  RotBox toParentCoords(const RotBox<dim>& coords) const
141  {return RotBox(m_corner0.toParentCoords(coords), m_size,
142  m_orient * coords.m_orient);}
143 
144  // toLocal is just like toParent, expect we reverse the order of
145  // translation and rotation and use the opposite sense of the rotation
146  // matrix
147 
148  RotBox toLocalCoords(const Point<dim>& origin,
149  const RotMatrix<dim>& rotation = RotMatrix<dim>().identity()) const
150  {return RotBox(m_corner0.toLocalCoords(origin, rotation), m_size,
151  rotation * m_orient);}
152  RotBox toLocalCoords(const AxisBox<dim>& coords) const
153  {return RotBox(m_corner0.toLocalCoords(coords), m_size, m_orient);}
154  RotBox toLocalCoords(const RotBox<dim>& coords) const
155  {return RotBox(m_corner0.toLocalCoords(coords), m_size,
156  coords.m_orient * m_orient);}
157 
158  // 3D only
159  RotBox toParentCoords(const Point<dim>& origin, const Quaternion& rotation) const;
160  RotBox toLocalCoords(const Point<dim>& origin, const Quaternion& rotation) const;
161 
162  friend bool Intersect<dim>(const RotBox& r, const Point<dim>& p, bool proper);
163  friend bool Contains<dim>(const Point<dim>& p, const RotBox& r, bool proper);
164 
165  friend bool Intersect<dim>(const RotBox& r, const AxisBox<dim>& b, bool proper);
166  friend bool Contains<dim>(const RotBox& r, const AxisBox<dim>& b, bool proper);
167  friend bool Contains<dim>(const AxisBox<dim>& b, const RotBox& r, bool proper);
168 
169  friend bool Intersect<dim>(const RotBox& r, const Ball<dim>& b, bool proper);
170  friend bool Contains<dim>(const RotBox& r, const Ball<dim>& b, bool proper);
171  friend bool Contains<dim>(const Ball<dim>& b, const RotBox& r, bool proper);
172 
173  friend bool Intersect<dim>(const RotBox& r, const Segment<dim>& s, bool proper);
174  friend bool Contains<dim>(const RotBox& r, const Segment<dim>& s, bool proper);
175  friend bool Contains<dim>(const Segment<dim>& s, const RotBox& r, bool proper);
176 
177  friend bool Intersect<dim>(const RotBox& r1, const RotBox& r2, bool proper);
178  friend bool Contains<dim>(const RotBox& outer, const RotBox& inner, bool proper);
179 
180  friend bool Intersect<dim>(const Polygon<dim>& p, const RotBox& r, bool proper);
181  friend bool Contains<dim>(const Polygon<dim>& p, const RotBox& r, bool proper);
182  friend bool Contains<dim>(const RotBox& r, const Polygon<dim>& p, bool proper);
183 
184  private:
185 
186  Point<dim> m_corner0;
187  Vector<dim> m_size;
188  RotMatrix<dim> m_orient;
189 };
190 
191 template<int dim>
192 inline RotBox<dim>& RotBox<dim>::operator=(const RotBox<dim>& a)
193 {
194  m_corner0 = a.m_corner0;
195  m_size = a.m_size;
196  m_orient = a.m_orient;
197 
198  return *this;
199 }
200 
201 template<int dim>
202 inline bool RotBox<dim>::isEqualTo(const RotBox<dim>& b, CoordType epsilon) const
203 {
204  return Equal(m_corner0, b.m_corner0, epsilon)
205  && Equal(m_size, b.m_size, epsilon)
206  && Equal(m_orient, b.m_orient, epsilon);
207 }
208 
209 } // namespace WFMath
210 
211 #endif // WFMATH_ROT_BOX_H