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 bool is_empty() const { return empty; }
31 bool is_negated() const { return negated; }
34 template<typename T, unsigned D>
35 inline BoundingBox<T, D>::BoundingBox():
40 template<typename T, unsigned D>
41 inline BoundingBox<T, D>::BoundingBox(const LinAl::Vector<T, D> &n, const LinAl::Vector<T, D> &x):
47 for(unsigned i=0; i<D; ++i)
48 if(min_pt[i]>max_pt[i])
49 throw std::invalid_argument("BoundingBox::BoundingBox");
52 template<typename T, unsigned D>
53 inline BoundingBox<T, D> BoundingBox<T, D>::negate(const BoundingBox<T, D> &bb)
55 BoundingBox<T, D> result = bb;
56 result.negated = !bb.negated;
60 template<typename T, unsigned D>
61 inline BoundingBox<T, D> operator&(const BoundingBox<T, D> &bb1, const BoundingBox<T, D> &bb2)
63 if(bb1.is_empty() || bb2.is_empty())
64 return BoundingBox<T, D>();
69 return ~((~bb1)|(~bb2));
74 LinAl::Vector<T, D> result_min;
75 LinAl::Vector<T, D> result_max;
79 // This is effectively subtraction of (non-negated) bb2 from bb1
80 int uncovered_axis = -1;
81 for(unsigned i=0; i<D; ++i)
82 if(bb1.get_minimum_coordinate(i)<bb2.get_minimum_coordinate(i) || bb1.get_maximum_coordinate(i)>bb2.get_maximum_coordinate(i))
84 if(uncovered_axis!=-1)
89 if(uncovered_axis==-1)
90 return BoundingBox<T, D>();
92 result_min = bb1.get_minimum_point();
93 result_max = bb1.get_maximum_point();
94 if(bb2.get_minimum_coordinate(uncovered_axis)<bb1.get_minimum_coordinate(uncovered_axis))
95 result_min[uncovered_axis] = bb2.get_maximum_coordinate(uncovered_axis);
97 result_max[uncovered_axis] = bb2.get_minimum_coordinate(uncovered_axis);
101 for(unsigned i=0; i<D; ++i)
103 result_min[i] = std::max(bb1.get_minimum_coordinate(i), bb1.get_minimum_coordinate(i));
104 result_max[i] = std::min(bb1.get_minimum_coordinate(i), bb1.get_minimum_coordinate(i));
105 if(result_min[i]>result_max[i])
106 return BoundingBox<T, D>();
110 return BoundingBox<T, D>(result_min, result_max);
113 template<typename T, unsigned D>
114 inline BoundingBox<T, D> operator|(const BoundingBox<T, D> &bb1, const BoundingBox<T, D> &bb2)
122 return ~((~bb1)&(~bb2));
123 else if(bb2.is_negated())
124 return ~((~bb2)&(~bb1));
126 LinAl::Vector<T, D> result_min;
127 LinAl::Vector<T, D> result_max;
128 for(unsigned i=0; i<D; ++i)
130 result_min[i] = std::min(bb1.get_minimum_coordinate(i), bb1.get_minimum_coordinate(i));
131 result_max[i] = std::max(bb1.get_minimum_coordinate(i), bb1.get_minimum_coordinate(i));
134 return BoundingBox<T, D>(result_min, result_max);
137 template<typename T, unsigned D>
138 inline BoundingBox<T, D> operator~(const BoundingBox<T, D> &bb)
140 return BoundingBox<T, D>::negate(bb);
143 } // namespace Geometry