X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fgeometry%2Fcompositeshape.h;h=f0b1f529544c12913202640c1e22604e5e5d5ded;hb=b7d1873aa023f4d4b81b32a3bce0b88e1e0e63ac;hp=50b04e80c506e93f7dc995187140e871dec66e27;hpb=827b227ae53884109b6885ccd1424dda8c0b3725;p=libs%2Fmath.git diff --git a/source/geometry/compositeshape.h b/source/geometry/compositeshape.h index 50b04e8..f0b1f52 100644 --- a/source/geometry/compositeshape.h +++ b/source/geometry/compositeshape.h @@ -1,6 +1,8 @@ #ifndef MSP_GEOMETRY_COMPOSITESHAPE_H_ #define MSP_GEOMETRY_COMPOSITESHAPE_H_ +#include +#include #include #include "shape.h" @@ -18,18 +20,24 @@ protected: typedef std::vector *> ShapeArray; ShapeArray shapes; + unsigned max_isect; + unsigned min_scratch; + CompositeShape() { } CompositeShape(const Shape &, const Shape &); - CompositeShape(const ShapeArray &); + template + void init_from_iter_range(const Iter &, const Iter &); +private: + void init(); +protected: CompositeShape(const CompositeShape &); CompositeShape &operator=(const CompositeShape &); public: virtual ~CompositeShape(); - virtual HyperBox get_axis_aligned_bounding_box() const; + virtual BoundingBox get_axis_aligned_bounding_box() const; virtual bool contains(const LinAl::Vector &) const; - virtual bool check_intersection(const Ray &) const; - virtual unsigned get_max_ray_intersections() const; + virtual unsigned get_max_ray_intersections() const { return max_isect; } virtual unsigned get_intersections(const Ray &, SurfacePoint *, unsigned) const; }; @@ -39,17 +47,56 @@ inline CompositeShape::CompositeShape(const Shape &s1, const Shap shapes.reserve(2); shapes.push_back(s1.clone()); shapes.push_back(s2.clone()); + init(); } template -inline CompositeShape::CompositeShape(const ShapeArray &s) +template +inline void CompositeShape::init_from_iter_range(const Iter &begin, const Iter &end) { - if(s.empty()) - throw std::invalid_argument("CompositeShape::CompositeShape"); + if(begin==end) + throw std::invalid_argument("CompositeShape::init_from_iter_range"); - shapes.reserve(s.size()); - for(typename ShapeArray::const_iterator i=s.begin(); i!=s.end(); ++i) + for(Iter i=begin; i!=end; ++i) shapes.push_back((*i)->clone()); + init(); +} + +template +inline void CompositeShape::init() +{ + max_isect = 0; + min_scratch = 0; + for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) + { + unsigned mi = (*i)->get_max_ray_intersections(); + max_isect += mi; + min_scratch = std::max(min_scratch, mi); + } +} + +template +inline CompositeShape::CompositeShape(const CompositeShape &other): + shapes(other.shapes), + max_isect(other.max_isect), + min_scratch(other.min_scratch) +{ + for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i) + *i = (*i)->clone(); +} + +template +inline CompositeShape &CompositeShape::operator=(const CompositeShape &other) +{ + for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i) + delete *i; + + shapes = other.shapes; + for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i) + *i = (*i)->clone(); + + max_isect = other.max_isect; + min_scratch = other.min_scratch; } template @@ -60,9 +107,9 @@ inline CompositeShape::~CompositeShape() } template -inline HyperBox CompositeShape::get_axis_aligned_bounding_box() const +inline BoundingBox CompositeShape::get_axis_aligned_bounding_box() const { - HyperBox aabb; + BoundingBox aabb; for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) { if(i==shapes.begin()) @@ -86,32 +133,25 @@ inline bool CompositeShape::contains(const LinAl::Vector &point) return inside; } -template -inline bool CompositeShape::check_intersection(const Ray &ray) const -{ - return get_intersections(ray, 0, 1); -} - -template -inline unsigned CompositeShape::get_max_ray_intersections() const -{ - unsigned max_isect = 0; - for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) - max_isect += (*i)->get_max_ray_intersections(); - return max_isect; -} - template inline unsigned CompositeShape::get_intersections(const Ray &ray, SurfacePoint *points, unsigned size) const { + SurfacePoint *buffer = points; + unsigned buf_size = size; + if(!points) + { + buffer = new SurfacePoint[min_scratch]; + buf_size = min_scratch; + } + unsigned n = 0; for(typename ShapeArray::const_iterator i=shapes.begin(); (nget_intersections(ray, points+base, size-base); + unsigned base = (points ? n : 0); + unsigned count = (*i)->get_intersections(ray, buffer+base, buf_size-base); for(unsigned j=0; (n &pt = points[base+j]; + SurfacePoint &pt = buffer[base+j]; bool surface = Ops::init_surface(); for(typename ShapeArray::const_iterator k=shapes.begin(); k!=shapes.end(); ++k) @@ -128,7 +168,10 @@ inline unsigned CompositeShape::get_intersections(const Ray &ray, } } - sort_points(points, n); + if(points) + sort_points(points, n); + else + delete[] buffer; return n; }