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