X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fgeometry%2Fcompositeshape.h;h=5d0cd8c59532ed3b782c3cd60908c8ce96778b6c;hb=44bd1d1ab256d397be4e2169c4ca5efdd0569d31;hp=55467d762993add17cbc4fe74ae7bfda2f776c22;hpb=5e5a34537e5f2efc71181f2bf6878c3e2e62b398;p=libs%2Fmath.git diff --git a/source/geometry/compositeshape.h b/source/geometry/compositeshape.h index 55467d7..5d0cd8c 100644 --- a/source/geometry/compositeshape.h +++ b/source/geometry/compositeshape.h @@ -1,6 +1,7 @@ #ifndef MSP_GEOMETRY_COMPOSITESHAPE_H_ #define MSP_GEOMETRY_COMPOSITESHAPE_H_ +#include #include #include #include "shape.h" @@ -19,20 +20,25 @@ protected: typedef std::vector *> ShapeArray; ShapeArray shapes; + unsigned max_isect; CompositeShape() { } CompositeShape(const Shape &, const Shape &); 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 BoundingBox get_axis_aligned_bounding_box() const; + virtual BoundingBox get_axis_aligned_bounding_box(unsigned = 0) const; virtual bool contains(const LinAl::Vector &) 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 @@ -41,6 +47,7 @@ inline CompositeShape::CompositeShape(const Shape &s1, const Shap shapes.reserve(2); shapes.push_back(s1.clone()); shapes.push_back(s2.clone()); + init(); } template @@ -52,11 +59,21 @@ inline void CompositeShape::init_from_iter_range(const Iter &begin, con 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) + shapes(other.shapes), + max_isect(other.max_isect) { for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i) *i = (*i)->clone(); @@ -71,6 +88,8 @@ inline CompositeShape &CompositeShape::operator=(const Composi shapes = other.shapes; for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i) *i = (*i)->clone(); + + max_isect = other.max_isect; } template @@ -81,8 +100,11 @@ inline CompositeShape::~CompositeShape() } template -inline BoundingBox CompositeShape::get_axis_aligned_bounding_box() const +inline BoundingBox CompositeShape::get_axis_aligned_bounding_box(unsigned detail) const { + if(detail) + return this->bisect_axis_aligned_bounding_box(detail); + BoundingBox aabb; for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i) { @@ -97,57 +119,98 @@ inline BoundingBox CompositeShape::get_axis_aligned_bounding_box( 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 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