1 #ifndef MSP_GEOMETRY_HYPERBOX_H_
2 #define MSP_GEOMETRY_HYPERBOX_H_
7 #include <msp/linal/vector.h>
14 A shape bounded by planar faces at right angles to each other. Two- and three-
15 dimensional cases are Rectangle and Box, respectively.
17 template<typename T, unsigned D>
18 class HyperBox: public Shape<T, D>
21 LinAl::Vector<T, D> dimensions;
25 explicit HyperBox(const LinAl::Vector<T, D> &);
27 virtual HyperBox *clone() const;
29 const LinAl::Vector<T, D> &get_dimensions() const { return dimensions; }
30 T get_dimension(unsigned) const;
32 virtual BoundingBox<T, D> get_axis_aligned_bounding_box(unsigned = 0) const;
33 virtual bool contains(const LinAl::Vector<T, D> &) const;
34 virtual unsigned get_max_ray_intersections() const { return 2; }
35 virtual unsigned get_intersections(const Ray<T, D> &, SurfacePoint<T, D> *, unsigned) const;
36 virtual Coverage get_coverage(const BoundingBox<T, D> &) const;
39 template<typename T, unsigned D>
40 inline HyperBox<T, D>::HyperBox()
42 for(unsigned i=0; i<D; ++i)
46 template<typename T, unsigned D>
47 inline HyperBox<T, D>::HyperBox(const LinAl::Vector<T, D> &d):
50 for(unsigned i=0; i<D; ++i)
51 if(dimensions[i]<=T(0))
52 throw std::invalid_argument("HyperBox::HyperBox");
55 template<typename T, unsigned D>
56 inline HyperBox<T, D> *HyperBox<T, D>::clone() const
58 return new HyperBox<T, D>(dimensions);
61 template<typename T, unsigned D>
62 inline T HyperBox<T, D>::get_dimension(unsigned i) const
67 template<typename T, unsigned D>
68 inline BoundingBox<T, D> HyperBox<T, D>::get_axis_aligned_bounding_box(unsigned) const
70 LinAl::Vector<T, D> half_dim = dimensions/T(2);
71 return BoundingBox<T, D>(-half_dim, half_dim);
74 template<typename T, unsigned D>
75 inline bool HyperBox<T, D>::contains(const LinAl::Vector<T, D> &point) const
79 for(unsigned i=0; i<D; ++i)
80 if(abs(point[i])>dimensions[i]/T(2))
85 template<typename T, unsigned D>
86 inline unsigned HyperBox<T, D>::get_intersections(const Ray<T, D> &ray, SurfacePoint<T, D> *points, unsigned size) const
93 LinAl::Vector<T, D> half_dim = dimensions/T(2);
95 for(unsigned i=0; (n<size && i<D); ++i)
97 if(!ray.get_direction()[i])
100 for(int j=-1; (n<size && j<=1); j+=2)
102 T x = (T(j)*half_dim[i]-ray.get_start()[i])/ray.get_direction()[i];
103 if(!ray.check_limits(x))
106 LinAl::Vector<T, D> p = ray.get_start()+ray.get_direction()*x;
109 for(unsigned k=0; (inside && k<D); ++k)
110 inside = (k==i || abs(p[k])<=half_dim[k]);
116 bool entry = (T(j)*ray.get_direction()[i]<T(0));
118 if(n>0 && entry!=points[0].entry)
121 points[1] = points[0];
125 if(k<n && entry==points[k].entry)
128 points[k].position = p;
129 points[k].normal = LinAl::Vector<T, D>();
130 points[k].normal[i] = j;
131 points[k].distance = x;
132 points[k].entry = (T(j)*ray.get_direction()[i]<T(0));
143 template<typename T, unsigned D>
144 inline Coverage HyperBox<T, D>::get_coverage(const BoundingBox<T, D> &bbox) const
146 const LinAl::Vector<T, D> &min_pt = bbox.get_minimum_point();
147 const LinAl::Vector<T, D> &max_pt = bbox.get_maximum_point();
148 LinAl::Vector<T, D> half_dim = dimensions/T(2);
150 Coverage coverage = FULL_COVERAGE;
151 for(unsigned i=0; i<D; ++i)
153 if(max_pt[i]<-half_dim[i] || min_pt[i]>half_dim[i])
155 if(min_pt[i]<-half_dim[i] || max_pt[i]>half_dim[i])
156 coverage = PARTIAL_COVERAGE;
162 } // namespace Geometry