WFMath  0.3.12
axisbox_funcs.h
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>
40 inline bool AxisBox<dim>::isEqualTo(const AxisBox<dim>& b, double epsilon) const
41 {
42  return Equal(m_low, b.m_low, epsilon)
43  && Equal(m_high, b.m_high, epsilon);
44 }
45 
46 template<int dim>
47 bool Intersection(const AxisBox<dim>& a1, const AxisBox<dim>& a2, AxisBox<dim>& out)
48 {
49  for(int i = 0; i < dim; ++i) {
50  out.m_low[i] = FloatMax(a1.m_low[i], a2.m_low[i]);
51  out.m_high[i] = FloatMin(a1.m_high[i], a2.m_high[i]);
52  if(out.m_low[i] > out.m_high[i])
53  return false;
54  }
55 
56  out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
57  out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
58 
59  return true;
60 }
61 
62 template<int dim>
63 AxisBox<dim> Union(const AxisBox<dim>& a1, const AxisBox<dim>& a2)
64 {
65  AxisBox<dim> out;
66 
67  for(int i = 0; i < dim; ++i) {
68  out.m_low[i] = FloatMin(a1.m_low[i], a2.m_low[i]);
69  out.m_high[i] = FloatMax(a1.m_high[i], a2.m_high[i]);
70  }
71 
72  out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
73  out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
74 
75  return out;
76 }
77 
78 template<int dim>
80  bool ordered)
81 {
82  if(ordered) {
83  m_low = p1;
84  m_high = p2;
85  return *this;
86  }
87 
88  for(int i = 0; i < dim; ++i) {
89  if(p1[i] > p2[i]) {
90  m_low[i] = p2[i];
91  m_high[i] = p1[i];
92  }
93  else {
94  m_low[i] = p1[i];
95  m_high[i] = p2[i];
96  }
97  }
98 
99  m_low.setValid();
100  m_high.setValid();
101 
102  return *this;
103 }
104 
105 template<int dim>
107 {
108  if(i < 1)
109  return m_low;
110  if(i >= (1 << dim) - 1)
111  return m_high;
112 
113  Point<dim> out;
114 
115  for(int j = 0; j < dim; ++j)
116  out[j] = (i & (1 << j)) ? m_high[j] : m_low[j];
117 
118  out.setValid(m_low.isValid() && m_high.isValid());
119 
120  return out;
121 }
122 
123 template<int dim>
124 inline Ball<dim> AxisBox<dim>::boundingSphere() const
125 {
126  return Ball<dim>(getCenter(), Distance(m_low, m_high) / 2);
127 }
128 
129 template<int dim>
130 inline Ball<dim> AxisBox<dim>::boundingSphereSloppy() const
131 {
132  return Ball<dim>(getCenter(), SloppyDistance(m_low, m_high) / 2);
133 }
134 
135 
136 template<int dim, template<class, class> class container>
137 AxisBox<dim> BoundingBox(const container<AxisBox<dim>, std::allocator<AxisBox<dim> > >& c)
138 {
139  // FIXME become friend
140 
141  typename container<AxisBox<dim>, std::allocator<AxisBox<dim> > >::const_iterator i = c.begin(), end = c.end();
142 
143  if(i == end) {
144  return AxisBox<dim>();
145  }
146 
147  Point<dim> low = i->lowCorner(), high = i->highCorner();
148  bool low_valid = low.isValid(), high_valid = high.isValid();
149 
150  while(++i != end) {
151  const Point<dim> &new_low = i->lowCorner(), &new_high = i->highCorner();
152  low_valid = low_valid && new_low.isValid();
153  high_valid = high_valid && new_high.isValid();
154  for(int j = 0; j < dim; ++j) {
155  low[j] = FloatMin(low[j], new_low[j]);
156  high[j] = FloatMax(high[j], new_high[j]);
157  }
158  }
159 
160  low.setValid(low_valid);
161  high.setValid(high_valid);
162 
163  return AxisBox<dim>(low, high, true);
164 }
165 
166 template<int dim, template<class, class> class container>
167 AxisBox<dim> BoundingBox(const container<Point<dim>, std::allocator<Point<dim> > >& c)
168 {
169  typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
170 
171  if(i == end) {
172  return AxisBox<dim>();
173  }
174 
175  Point<dim> low = *i, high = *i;
176  bool valid = i->isValid();
177 
178  while(++i != end) {
179  valid = valid && i->isValid();
180  for(int j = 0; j < dim; ++j) {
181  low[j] = FloatMin(low[j], (*i)[j]);
182  high[j] = FloatMax(high[j], (*i)[j]);
183  }
184  }
185 
186  low.setValid(valid);
187  high.setValid(valid);
188 
189  return AxisBox<dim>(low, high, true);
190 }
191 
192 // This is here, instead of defined in the class, to
193 // avoid include order problems
194 
195 template<int dim>
196 inline AxisBox<dim> Point<dim>::boundingBox() const
197 {
198  return AxisBox<dim>(*this, *this, true);
199 }
200 
201 template<int dim>
202 Point<dim> Point<dim>::toParentCoords(const AxisBox<dim>& coords) const
203 {
204  return coords.lowCorner() + (*this - Point().setToOrigin());
205 }
206 
207 template<int dim>
208 Point<dim> Point<dim>::toLocalCoords(const AxisBox<dim>& coords) const
209 {
210  return Point().setToOrigin() + (*this - coords.lowCorner());
211 }
212 
213 } // namespace WFMath
214 
215 #endif // WFMATH_AXIS_BOX_FUNCS_H
A dim dimensional axis-aligned box.
Definition: axisbox.h:62
AxisBox & setCorners(const Point< dim > &p1, const Point< dim > &p2, bool ordered=false)
Set the box to have opposite corners p1 and p2.
Definition: axisbox_funcs.h:79
bool Equal(const C &c1, const C &c2, double epsilon=WFMATH_EPSILON)
Test for equality up to precision epsilon.
Definition: const.h:103
const Point< dim > & lowCorner() const
Get a reference to corner 0.
Definition: axisbox.h:100
void setValid(bool valid=true)
make isValid() return true if you've initialized the point by hand
Definition: point.h:129
A dim dimensional point.
Definition: const.h:50
AxisBox< dim > BoundingBox(const container< AxisBox< dim >, std::allocator< AxisBox< dim > > > &c)
Get the axis-aligned bounding box for a set of boxes.
Definition: axisbox_funcs.h:137