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 && !negated; }
31 bool is_space() const { return empty && negated; }
32 bool is_negated() const { return negated; }
35 template<typename T, unsigned D>
36 inline BoundingBox<T, D>::BoundingBox():
41 template<typename T, unsigned D>
42 inline BoundingBox<T, D>::BoundingBox(const LinAl::Vector<T, D> &n, const LinAl::Vector<T, D> &x):
48 for(unsigned i=0; i<D; ++i)
49 if(min_pt[i]>max_pt[i])
50 throw std::invalid_argument("BoundingBox::BoundingBox");
53 template<typename T, unsigned D>
54 inline BoundingBox<T, D> BoundingBox<T, D>::negate(const BoundingBox<T, D> &bb)
56 BoundingBox<T, D> result = bb;
57 result.negated = !bb.negated;
61 template<typename T, unsigned D>
62 inline BoundingBox<T, D> operator&(const BoundingBox<T, D> &bb1, const BoundingBox<T, D> &bb2)
64 if(bb1.is_empty() || bb2.is_empty())
65 return BoundingBox<T, D>();
70 return ~((~bb1)|(~bb2));
75 LinAl::Vector<T, D> result_min;
76 LinAl::Vector<T, D> result_max;
80 // This is effectively subtraction of (non-negated) bb2 from bb1
81 int uncovered_axis = -1;
82 for(unsigned i=0; i<D; ++i)
83 if(bb1.get_minimum_coordinate(i)<bb2.get_minimum_coordinate(i) || bb1.get_maximum_coordinate(i)>bb2.get_maximum_coordinate(i))
85 if(uncovered_axis!=-1)
90 if(uncovered_axis==-1)
91 return BoundingBox<T, D>();
93 result_min = bb1.get_minimum_point();
94 result_max = bb1.get_maximum_point();
95 if(bb2.get_minimum_coordinate(uncovered_axis)<bb1.get_minimum_coordinate(uncovered_axis))
96 result_min[uncovered_axis] = bb2.get_maximum_coordinate(uncovered_axis);
98 result_max[uncovered_axis] = bb2.get_minimum_coordinate(uncovered_axis);
102 for(unsigned i=0; i<D; ++i)
104 result_min[i] = std::max(bb1.get_minimum_coordinate(i), bb2.get_minimum_coordinate(i));
105 result_max[i] = std::min(bb1.get_maximum_coordinate(i), bb2.get_maximum_coordinate(i));
106 if(result_min[i]>result_max[i])
107 return BoundingBox<T, D>();
111 return BoundingBox<T, D>(result_min, result_max);
114 template<typename T, unsigned D>
115 inline BoundingBox<T, D> operator|(const BoundingBox<T, D> &bb1, const BoundingBox<T, D> &bb2)
123 return ~((~bb1)&(~bb2));
124 else if(bb2.is_negated())
125 return ~((~bb2)&(~bb1));
127 LinAl::Vector<T, D> result_min;
128 LinAl::Vector<T, D> result_max;
129 for(unsigned i=0; i<D; ++i)
131 result_min[i] = std::min(bb1.get_minimum_coordinate(i), bb2.get_minimum_coordinate(i));
132 result_max[i] = std::max(bb1.get_maximum_coordinate(i), bb2.get_maximum_coordinate(i));
135 return BoundingBox<T, D>(result_min, result_max);
138 template<typename T, unsigned D>
139 inline BoundingBox<T, D> operator~(const BoundingBox<T, D> &bb)
141 return BoundingBox<T, D>::negate(bb);
144 } // namespace Geometry