1 // axisbox_funcs.h (Axis-aligned box implementation)
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 // The implementation of this class is based on the geometric
27 // parts of the Tree and Placement classes from stage/shepherd/sylvanus
28 
29 #ifndef WFMATH_AXIS_BOX_FUNCS_H
30 #define WFMATH_AXIS_BOX_FUNCS_H
31 
32 #include <wfmath/axisbox.h>
33 
34 #include <wfmath/point.h>
35 #include <wfmath/ball.h>
36 
37 namespace WFMath {
38 
39 template<int dim>
Intersection(const AxisBox<dim> & a1,const AxisBox<dim> & a2,AxisBox<dim> & out)40 bool Intersection(const AxisBox<dim>& a1, const AxisBox<dim>& a2, AxisBox<dim>& out)
41 {
42   for(int i = 0; i < dim; ++i) {
43     out.m_low[i] = FloatMax(a1.m_low[i], a2.m_low[i]);
44     out.m_high[i] = FloatMin(a1.m_high[i], a2.m_high[i]);
45     if(out.m_low[i] > out.m_high[i])
46       return false;
47   }
48 
49   out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
50   out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
51 
52   return true;
53 }
54 
55 template<int dim>
Union(const AxisBox<dim> & a1,const AxisBox<dim> & a2)56 AxisBox<dim> Union(const AxisBox<dim>& a1, const AxisBox<dim>& a2)
57 {
58   AxisBox<dim> out;
59 
60   for(int i = 0; i < dim; ++i) {
61     out.m_low[i] = FloatMin(a1.m_low[i], a2.m_low[i]);
62     out.m_high[i] = FloatMax(a1.m_high[i], a2.m_high[i]);
63   }
64 
65   out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
66   out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
67 
68   return out;
69 }
70 
71 template<int dim>
setCorners(const Point<dim> & p1,const Point<dim> & p2,bool ordered)72 AxisBox<dim>& AxisBox<dim>::setCorners(const Point<dim>& p1, const Point<dim>& p2,
73 				       bool ordered)
74 {
75   if(ordered) {
76     m_low = p1;
77     m_high = p2;
78     return *this;
79   }
80 
81   for(int i = 0; i < dim; ++i) {
82     if(p1[i] > p2[i]) {
83       m_low[i] = p2[i];
84       m_high[i] = p1[i];
85     }
86     else {
87       m_low[i] = p1[i];
88       m_high[i] = p2[i];
89     }
90   }
91 
92   m_low.setValid();
93   m_high.setValid();
94 
95   return *this;
96 }
97 
98 template<int dim>
getCorner(size_t i)99 Point<dim> AxisBox<dim>::getCorner(size_t i) const
100 {
101   if(i < 1)
102     return m_low;
103   if(i >= (1 << dim) - 1)
104     return m_high;
105 
106   Point<dim> out;
107 
108   for(int j = 0; j < dim; ++j)
109     out[j] = (i & (1 << j)) ? m_high[j] : m_low[j];
110 
111   out.setValid(m_low.isValid() && m_high.isValid());
112 
113   return out;
114 }
115 
116 template<int dim>
boundingSphere()117 inline Ball<dim> AxisBox<dim>::boundingSphere() const
118 {
119   return Ball<dim>(getCenter(), Distance(m_low, m_high) / 2);
120 }
121 
122 template<int dim>
boundingSphereSloppy()123 inline Ball<dim> AxisBox<dim>::boundingSphereSloppy() const
124 {
125   return Ball<dim>(getCenter(), SloppyDistance(m_low, m_high) / 2);
126 }
127 
128 
129 template<int dim, template<class, class> class container>
BoundingBox(const container<AxisBox<dim>,std::allocator<AxisBox<dim>>> & c)130 AxisBox<dim> BoundingBox(const container<AxisBox<dim>, std::allocator<AxisBox<dim> > >& c)
131 {
132   typename container<AxisBox<dim>, std::allocator<AxisBox<dim> > >::const_iterator i = c.begin(), end = c.end();
133 
134   if(i == end) {
135     return AxisBox<dim>();
136   }
137 
138   Point<dim> low = i->lowCorner(), high = i->highCorner();
139   bool low_valid = low.isValid(), high_valid = high.isValid();
140 
141   while(++i != end) {
142     const Point<dim> &new_low = i->lowCorner(), &new_high = i->highCorner();
143     low_valid = low_valid && new_low.isValid();
144     high_valid = high_valid && new_high.isValid();
145     for(int j = 0; j < dim; ++j) {
146       low[j] = FloatMin(low[j], new_low[j]);
147       high[j] = FloatMax(high[j], new_high[j]);
148     }
149   }
150 
151   low.setValid(low_valid);
152   high.setValid(high_valid);
153 
154   return AxisBox<dim>(low, high, true);
155 }
156 
157 template<int dim, template<class, class> class container>
BoundingBox(const container<Point<dim>,std::allocator<Point<dim>>> & c)158 AxisBox<dim> BoundingBox(const container<Point<dim>, std::allocator<Point<dim> > >& c)
159 {
160   typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
161 
162   if(i == end) {
163     return AxisBox<dim>();
164   }
165 
166   Point<dim> low = *i, high = *i;
167   bool valid = i->isValid();
168 
169   while(++i != end) {
170     valid = valid && i->isValid();
171     for(int j = 0; j < dim; ++j) {
172       low[j] = FloatMin(low[j], (*i)[j]);
173       high[j] = FloatMax(high[j], (*i)[j]);
174     }
175   }
176 
177   low.setValid(valid);
178   high.setValid(valid);
179 
180   return AxisBox<dim>(low, high, true);
181 }
182 
183 // This is here, instead of defined in the class, to
184 // avoid include order problems
185 
186 template<int dim>
boundingBox()187 inline AxisBox<dim> Point<dim>::boundingBox() const
188 {
189   return AxisBox<dim>(*this, *this, true);
190 }
191 
192 template<int dim>
toParentCoords(const AxisBox<dim> & coords)193 Point<dim> Point<dim>::toParentCoords(const AxisBox<dim>& coords) const
194 {
195   return coords.lowCorner() + (*this - Point().setToOrigin());
196 }
197 
198 template<int dim>
toLocalCoords(const AxisBox<dim> & coords)199 Point<dim> Point<dim>::toLocalCoords(const AxisBox<dim>& coords) const
200 {
201   return Point().setToOrigin() + (*this - coords.lowCorner());
202 }
203 
204 } // namespace WFMath
205 
206 #endif  // WFMATH_AXIS_BOX_FUNCS_H
207