Code structure in simpler shapes have been adjusted to keep it similar.
inline unsigned CompositeShape<T, D, O>::get_intersections(const Ray<T, D> &ray, SurfacePoint<T, D> *points, unsigned size) const
{
unsigned n = 0;
- for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
+ for(typename ShapeArray::const_iterator i=shapes.begin(); (n<size && i!=shapes.end()); ++i)
{
unsigned base = n;
unsigned count = (*i)->get_intersections(ray, points+base, size-base);
- for(unsigned j=0; j<count; ++j)
+ for(unsigned j=0; (n<size && j<count); ++j)
{
- // XXX Devise a way to reduce copies here
- SurfacePoint<T, D> pt = points[base+j];
+ SurfacePoint<T, D> &pt = points[base+j];
bool surface = Ops::init_surface();
for(typename ShapeArray::const_iterator k=shapes.begin(); k!=shapes.end(); ++k)
if(surface)
{
- if(points)
- {
- unsigned k;
- for(k=n; (k>0 && points[k-1].distance>pt.distance); --k)
- points[k] = points[k-1];
- if(base+j!=k)
- points[k] = pt;
- }
+ if(points && base+j!=n)
+ points[n] = pt;
++n;
- if(n==size)
- return n;
}
}
}
+ sort_points(points, n);
+
return n;
}
base_points = reinterpret_cast<SurfacePoint<T, D-1> *>(points+size)-size;
unsigned count = base->get_intersections(base_ray, base_points, size);
- for(unsigned i=0; i<count; ++i)
+ for(unsigned i=0; (n<size && i<count); ++i)
{
if(points)
{
}
++n;
- if(n==size)
- return n;
}
}
/* If the ray is not parallel to the base space, it may pass through the
caps. */
- if(ray_direction[D-1])
+ if(n<size && ray_direction[D-1])
{
- for(int i=-1; i<=1; i+=2)
+ for(int i=-1; (n<size && i<=1); i+=2)
{
T x = (half_length*i-ray_start[D-1])/ray_direction[D-1];
if(!ray.check_limits(x))
continue;
LinAl::Vector<T, D> p = ray_start+ray_direction*x;
- if(base->contains(LinAl::Vector<T, D-1>(p)) && n<size)
+ if(base->contains(LinAl::Vector<T, D-1>(p)))
{
if(points)
{
points[n].normal = LinAl::Vector<T, D>();
points[n].normal[D-1] = i;
points[n].distance = x;
-
- if(n==1 && x<points[0].distance)
- swap(points[0], points[1]);
}
++n;
- if(n==size)
- return n;
}
}
+
+ sort_points(points, n);
}
return n;
{
using std::abs;
+ if(size>2)
+ size = 2;
+
LinAl::Vector<T, D> half_dim = dimensions/T(2);
unsigned n = 0;
- for(unsigned i=0; i<D; ++i)
+ for(unsigned i=0; (n<size && i<D); ++i)
{
if(!ray.get_direction()[i])
continue;
- for(int j=-1; j<=1; j+=2)
+ for(int j=-1; (n<size && j<=1); j+=2)
{
T x = (T(j)*half_dim[i]-ray.get_start()[i])/ray.get_direction()[i];
if(!ray.check_limits(x))
for(unsigned k=0; (inside && k<D); ++k)
inside = (k==i || abs(p[k])<=half_dim[k]);
- if(inside && n<size)
+ if(inside)
{
if(points)
{
}
++n;
- if(n==size || n==2)
- return n;
}
}
}
T offset = sqrt(offset_sq);
unsigned n = 0;
- for(int i=-1; i<=1; i+=2)
+ for(int i=-1; (n<size && i<=1); i+=2)
{
T x = mid+offset*i;
- if(ray.check_limits(x) && n<size)
+ if(ray.check_limits(x))
{
if(points)
{
}
++n;
- if(n==size)
- return n;
}
}
#ifndef MSP_GEOMETRY_SURFACEPOINT_H_
#define MSP_GEOMETRY_SURFACEPOINT_H_
+#include <algorithm>
#include <msp/linal/vector.h>
namespace Msp {
T distance;
};
+template<typename T, unsigned N>
+void sort_points(SurfacePoint<T, N> *points, unsigned size)
+{
+ for(unsigned i=0; i<size; ++i)
+ {
+ unsigned n = i;
+ for(unsigned j=i+1; j<size; ++j)
+ if(points[j].distance<points[n].distance)
+ n = j;
+ if(n!=i)
+ std::swap(points[i], points[n]);
+ }
+}
+
} // namespace Geometry
} // namespace Msp