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;
26 CompositeShape(const Shape<T, D> &, const Shape<T, D> &);
27 template<typename Iter>
28 void init_from_iter_range(const Iter &, const Iter &);
32 CompositeShape(const CompositeShape &);
33 CompositeShape &operator=(const CompositeShape &);
35 virtual ~CompositeShape();
37 virtual BoundingBox<T, D> get_axis_aligned_bounding_box(unsigned = 0) const;
38 virtual bool contains(const LinAl::Vector<T, D> &) const;
39 virtual unsigned get_max_ray_intersections() const { return max_isect; }
40 virtual unsigned get_intersections(const Ray<T, D> &, SurfacePoint<T, D> *, unsigned) const;
41 virtual Coverage get_coverage(const BoundingBox<T, D> &) 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()
69 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
70 max_isect += (*i)->get_max_ray_intersections();
73 template<typename T, unsigned D, typename O>
74 inline CompositeShape<T, D, O>::CompositeShape(const CompositeShape<T, D, O> &other):
76 max_isect(other.max_isect)
78 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
82 template<typename T, unsigned D, typename O>
83 inline CompositeShape<T, D, O> &CompositeShape<T, D, O>::operator=(const CompositeShape<T, D, O> &other)
85 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
88 shapes = other.shapes;
89 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
92 max_isect = other.max_isect;
95 template<typename T, unsigned D, typename O>
96 inline CompositeShape<T, D, O>::~CompositeShape()
98 for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
102 template<typename T, unsigned D, typename O>
103 inline BoundingBox<T, D> CompositeShape<T, D, O>::get_axis_aligned_bounding_box(unsigned detail) const
106 return this->bisect_axis_aligned_bounding_box(detail);
108 BoundingBox<T, D> aabb;
109 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
111 if(i==shapes.begin())
112 aabb = (*i)->get_axis_aligned_bounding_box();
114 aabb = Ops::combine_aabb(aabb, (*i)->get_axis_aligned_bounding_box());
119 template<typename T, unsigned D, typename O>
120 inline bool CompositeShape<T, D, O>::contains(const LinAl::Vector<T, D> &point) const
123 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
125 inside = (*i)->contains(point);
126 if(Ops::shortcircuit(inside))
132 template<typename T, unsigned D, typename O>
133 inline unsigned CompositeShape<T, D, O>::get_intersections(const Ray<T, D> &ray, SurfacePoint<T, D> *points, unsigned size) const
135 SurfacePoint<T, D> *buffer = points;
136 unsigned buf_size = size;
137 if(!points && !Ops::shortcircuit(true))
139 buffer = new SurfacePoint<T, D>[max_isect];
140 buf_size = max_isect;
143 int start_nesting = 0;
145 for(typename ShapeArray::const_iterator i=shapes.begin(); (n<buf_size && i!=shapes.end()); ++i)
148 unsigned count = (*i)->get_intersections(ray, buffer+base, buf_size-base);
149 bool start_inside = (*i)->contains(ray.get_start());
151 if(!count && !start_inside)
153 if(Ops::shortcircuit(false))
158 start_nesting += start_inside;
166 sort_points(buffer, base+count);
168 int nesting = start_nesting;
170 for(unsigned j=0; j<base+count; ++j)
172 if(Ops::shortcircuit(nesting+buffer[j].entry<2))
175 buffer[k] = buffer[j];
179 nesting += buffer[j].entry*2-1;
182 if(!k && Ops::shortcircuit(false))
187 if(i!=shapes.begin())
188 start_nesting = (start_nesting>!Ops::shortcircuit(true));
197 template<typename T, unsigned D, typename O>
198 inline Coverage CompositeShape<T, D, O>::get_coverage(const BoundingBox<T, D> &bbox) const
200 Coverage coverage = NO_COVERAGE;
201 for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
203 Coverage c = (*i)->get_coverage(bbox);
204 if(i==shapes.begin())
207 coverage = Ops::combine_coverage(coverage, c);
209 if((coverage==NO_COVERAGE && Ops::shortcircuit(false)) || (coverage==FULL_COVERAGE && Ops::shortcircuit(true)))
216 } // namespace Geometry