1 #ifndef MSP_GEOMETRY_COMPOSITESHAPE_H_
2 #define MSP_GEOMETRY_COMPOSITESHAPE_H_
13 Common operations for shapes composed of other shapes.
15 template<typename T, unsigned D, typename O>
16 class CompositeShape: public Shape<T, D>
20 typedef std::vector<Shape<T, D> *> ShapeArray;
27 CompositeShape(const Shape<T, D> &, const Shape<T, D> &);
28 template<typename Iter>
29 void init_from_iter_range(const Iter &, const Iter &);
33 CompositeShape(const CompositeShape &);
34 CompositeShape &operator=(const CompositeShape &);
36 virtual ~CompositeShape();
38 virtual BoundingBox<T, D> get_axis_aligned_bounding_box() const;
39 virtual bool contains(const LinAl::Vector<T, D> &) const;
40 virtual unsigned get_max_ray_intersections() const { return max_isect; }
41 virtual unsigned get_intersections(const Ray<T, D> &, SurfacePoint<T, D> *, unsigned) const;
44 template<typename T, unsigned D, typename O>
45 inline CompositeShape<T, D, O>::CompositeShape(const Shape<T, D> &s1, const Shape<T, D> &s2)
48 shapes.push_back(s1.clone());
49 shapes.push_back(s2.clone());
53 template<typename T, unsigned D, typename O>
54 template<typename Iter>
55 inline void CompositeShape<T, D, O>::init_from_iter_range(const Iter &begin, const Iter &end)
58 throw std::invalid_argument("CompositeShape::init_from_iter_range");
60 for(Iter i=begin; i!=end; ++i)
61 shapes.push_back((*i)->clone());
65 template<typename T, unsigned D, typename O>
66 inline void CompositeShape<T, D, O>::init()
70 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
72 unsigned mi = (*i)->get_max_ray_intersections();
74 min_scratch = std::max(min_scratch, mi);
78 template<typename T, unsigned D, typename O>
79 inline CompositeShape<T, D, O>::CompositeShape(const CompositeShape<T, D, O> &other):
81 max_isect(other.max_isect),
82 min_scratch(other.min_scratch)
84 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
88 template<typename T, unsigned D, typename O>
89 inline CompositeShape<T, D, O> &CompositeShape<T, D, O>::operator=(const CompositeShape<T, D, O> &other)
91 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
94 shapes = other.shapes;
95 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
98 max_isect = other.max_isect;
99 min_scratch = other.min_scratch;
102 template<typename T, unsigned D, typename O>
103 inline CompositeShape<T, D, O>::~CompositeShape()
105 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
109 template<typename T, unsigned D, typename O>
110 inline BoundingBox<T, D> CompositeShape<T, D, O>::get_axis_aligned_bounding_box() const
112 BoundingBox<T, D> aabb;
113 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
115 if(i==shapes.begin())
116 aabb = (*i)->get_axis_aligned_bounding_box();
118 aabb = Ops::combine_aabb(aabb, (*i)->get_axis_aligned_bounding_box());
123 template<typename T, unsigned D, typename O>
124 inline bool CompositeShape<T, D, O>::contains(const LinAl::Vector<T, D> &point) const
126 bool inside = Ops::init_inside();
127 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
129 inside = Ops::combine_inside(inside, (*i)->contains(point));
130 if(Ops::is_inside_decided(inside))
136 template<typename T, unsigned D, typename O>
137 inline unsigned CompositeShape<T, D, O>::get_intersections(const Ray<T, D> &ray, SurfacePoint<T, D> *points, unsigned size) const
139 SurfacePoint<T, D> *buffer = points;
140 unsigned buf_size = size;
143 buffer = new SurfacePoint<T, D>[min_scratch];
144 buf_size = min_scratch;
148 for(typename ShapeArray::const_iterator i=shapes.begin(); (n<size && i!=shapes.end()); ++i)
150 unsigned base = (points ? n : 0);
151 unsigned count = (*i)->get_intersections(ray, buffer+base, buf_size-base);
152 for(unsigned j=0; (n<size && j<count); ++j)
154 SurfacePoint<T, D> &pt = buffer[base+j];
156 bool surface = Ops::init_surface();
157 for(typename ShapeArray::const_iterator k=shapes.begin(); k!=shapes.end(); ++k)
159 surface = Ops::combine_surface(surface, (*k)->contains(pt.position));
163 if(points && base+j!=n)
172 sort_points(points, n);
179 } // namespace Geometry