X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fgeometry%2Fcompositeshape.h;h=5d0cd8c59532ed3b782c3cd60908c8ce96778b6c;hb=44bd1d1ab256d397be4e2169c4ca5efdd0569d31;hp=50b04e80c506e93f7dc995187140e871dec66e27;hpb=827b227ae53884109b6885ccd1424dda8c0b3725;p=libs%2Fmath.git diff --git a/source/geometry/compositeshape.h b/source/geometry/compositeshape.h index 50b04e8..5d0cd8c 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,19 +20,25 @@ protected: typedef std::vector *> ShapeArray; ShapeArray shapes; + unsigned max_isect; + 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(unsigned = 0) 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; + virtual Coverage get_coverage(const BoundingBox &) const; }; template @@ -39,17 +47,49 @@ 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; + for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) + max_isect += (*i)->get_max_ray_intersections(); +} + +template +inline CompositeShape::CompositeShape(const CompositeShape &other): + shapes(other.shapes), + max_isect(other.max_isect) +{ + 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; } template @@ -60,9 +100,12 @@ inline CompositeShape::~CompositeShape() } template -inline HyperBox CompositeShape::get_axis_aligned_bounding_box() const +inline BoundingBox CompositeShape::get_axis_aligned_bounding_box(unsigned detail) const { - HyperBox aabb; + if(detail) + return this->bisect_axis_aligned_bounding_box(detail); + + BoundingBox aabb; for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) { if(i==shapes.begin()) @@ -76,63 +119,98 @@ inline HyperBox CompositeShape::get_axis_aligned_bounding_box() c template inline bool CompositeShape::contains(const LinAl::Vector &point) const { - bool inside = Ops::init_inside(); + bool inside = false; for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) { - inside = Ops::combine_inside(inside, (*i)->contains(point)); - if(Ops::is_inside_decided(inside)) - break; + inside = (*i)->contains(point); + if(Ops::shortcircuit(inside)) + return inside; } 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 && !Ops::shortcircuit(true)) + { + buffer = new SurfacePoint[max_isect]; + buf_size = max_isect; + } + + int start_nesting = 0; unsigned n = 0; - for(typename ShapeArray::const_iterator i=shapes.begin(); (nget_intersections(ray, points+base, size-base); - for(unsigned j=0; (nget_intersections(ray, buffer+base, buf_size-base); + bool start_inside = (*i)->contains(ray.get_start()); + + if(!count && !start_inside) { - SurfacePoint &pt = points[base+j]; + if(Ops::shortcircuit(false)) + return 0; + continue; + } - bool surface = Ops::init_surface(); - for(typename ShapeArray::const_iterator k=shapes.begin(); k!=shapes.end(); ++k) - if(k!=i) - surface = Ops::combine_surface(surface, (*k)->contains(pt.position)); + start_nesting += start_inside; - if(surface) - { - if(points && base+j!=n) - points[n] = pt; + if(!base) + { + n = count; + continue; + } - ++n; + sort_points(buffer, base+count); + + int nesting = start_nesting; + unsigned k = 0; + for(unsigned j=0; j!Ops::shortcircuit(true)); } - sort_points(points, n); + if(buffer!=points) + delete[] buffer; return n; } +template +inline Coverage CompositeShape::get_coverage(const BoundingBox &bbox) const +{ + Coverage coverage = NO_COVERAGE; + for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) + { + Coverage c = (*i)->get_coverage(bbox); + if(i==shapes.begin() || Ops::shortcircuit(c>coverage)) + coverage = c; + + if(coverage!=PARTIAL_COVERAGE && Ops::shortcircuit(coverage==FULL_COVERAGE)) + break; + } + + return coverage; +} + } // namespace Geometry } // namespace Msp