1 #ifndef MSP_GEOMETRY_BOUNDINGBOX_H_
2 #define MSP_GEOMETRY_BOUNDINGBOX_H_
6 #include <msp/linal/vector.h>
11 template<typename T, unsigned D>
15 LinAl::Vector<T, D> min_pt;
16 LinAl::Vector<T, D> max_pt;
22 BoundingBox(const LinAl::Vector<T, D> &, const LinAl::Vector<T, D> &);
24 static BoundingBox negate(const BoundingBox &);
26 const LinAl::Vector<T, D> &get_minimum_point() const { return min_pt; }
27 T get_minimum_coordinate(unsigned i) const { return min_pt[i]; }
28 const LinAl::Vector<T, D> &get_maximum_point() const { return max_pt; }
29 T get_maximum_coordinate(unsigned i) const { return max_pt[i]; }
30 LinAl::Vector<T, D> get_dimensions() const { return max_pt-min_pt; }
31 T get_dimension(unsigned i) const { return max_pt[i]-min_pt[i]; }
33 bool is_empty() const { return empty && !negated; }
34 bool is_space() const { return empty && negated; }
35 bool is_negated() const { return negated; }
38 template<typename T, unsigned D>
39 inline BoundingBox<T, D>::BoundingBox():
44 template<typename T, unsigned D>
45 inline BoundingBox<T, D>::BoundingBox(const LinAl::Vector<T, D> &n, const LinAl::Vector<T, D> &x):
51 for(unsigned i=0; i<D; ++i)
52 if(min_pt[i]>max_pt[i])
53 throw std::invalid_argument("BoundingBox::BoundingBox");
56 template<typename T, unsigned D>
57 inline BoundingBox<T, D> BoundingBox<T, D>::negate(const BoundingBox<T, D> &bb)
59 BoundingBox<T, D> result = bb;
60 result.negated = !bb.negated;
64 template<typename T, unsigned D>
65 inline BoundingBox<T, D> operator&(const BoundingBox<T, D> &bb1, const BoundingBox<T, D> &bb2)
67 if(bb1.is_empty() || bb2.is_empty())
68 return BoundingBox<T, D>();
73 return ~((~bb1)|(~bb2));
78 LinAl::Vector<T, D> result_min;
79 LinAl::Vector<T, D> result_max;
83 // This is effectively subtraction of (non-negated) bb2 from bb1
84 int uncovered_axis = -1;
85 for(unsigned i=0; i<D; ++i)
86 if(bb1.get_minimum_coordinate(i)<bb2.get_minimum_coordinate(i) || bb1.get_maximum_coordinate(i)>bb2.get_maximum_coordinate(i))
88 if(uncovered_axis!=-1)
93 if(uncovered_axis==-1)
94 return BoundingBox<T, D>();
96 result_min = bb1.get_minimum_point();
97 result_max = bb1.get_maximum_point();
98 if(bb2.get_minimum_coordinate(uncovered_axis)<bb1.get_minimum_coordinate(uncovered_axis))
99 result_min[uncovered_axis] = bb2.get_maximum_coordinate(uncovered_axis);
101 result_max[uncovered_axis] = bb2.get_minimum_coordinate(uncovered_axis);
105 for(unsigned i=0; i<D; ++i)
107 result_min[i] = std::max(bb1.get_minimum_coordinate(i), bb2.get_minimum_coordinate(i));
108 result_max[i] = std::min(bb1.get_maximum_coordinate(i), bb2.get_maximum_coordinate(i));
109 if(result_min[i]>result_max[i])
110 return BoundingBox<T, D>();
114 return BoundingBox<T, D>(result_min, result_max);
117 template<typename T, unsigned D>
118 inline BoundingBox<T, D> operator|(const BoundingBox<T, D> &bb1, const BoundingBox<T, D> &bb2)
126 return ~((~bb1)&(~bb2));
127 else if(bb2.is_negated())
128 return ~((~bb2)&(~bb1));
130 LinAl::Vector<T, D> result_min;
131 LinAl::Vector<T, D> result_max;
132 for(unsigned i=0; i<D; ++i)
134 result_min[i] = std::min(bb1.get_minimum_coordinate(i), bb2.get_minimum_coordinate(i));
135 result_max[i] = std::max(bb1.get_maximum_coordinate(i), bb2.get_maximum_coordinate(i));
138 return BoundingBox<T, D>(result_min, result_max);
141 template<typename T, unsigned D>
142 inline BoundingBox<T, D> operator~(const BoundingBox<T, D> &bb)
144 return BoundingBox<T, D>::negate(bb);
147 } // namespace Geometry