bool rayIntersects(RayN<N, T> const & ray, T max_time = -1) const { if (max_time >= 0) return rayIntersectionTime(ray, max_time) >= 0; VectorT co = ray.getOrigin() - center; T c = co.squaredNorm() - radius * radius; if (c <= 0) // origin is inside ball return true; T a = ray.getDirection().squaredNorm(); T b = 2 * co.dot(ray.getDirection()); // Solve quadratic a * t^2 + b * t + c = 0 T b2 = b * b; T det = b2 - 4 * a * c; if (det < 0) return false; if (a > 0) return b <= 0 || det >= b2; else if (a < 0) return b >= 0 || det >= b2; else return false; }
T rayIntersectionTime(RayN<N, T> const & ray, T max_time = -1) const { VectorT co = ray.getOrigin() - center; T c = co.squaredNorm() - radius * radius; if (c <= 0) // origin is inside ball return 0; // We could do an early test to see if the distance from the ray origin to the ball is less than // max_time * ray.getDirection().norm(), but it would involve a square root so might as well solve the quadratic. T a = ray.getDirection().squaredNorm(); T b = 2 * co.dot(ray.getDirection()); // Solve quadratic a * t^2 + b * t + c = 0 T det = b * b - 4 * a * c; if (det < 0) return -1; T d = std::sqrt(det); T t = -1; if (a > 0) { T s0 = -b - d; if (s0 >= 0) t = s0 / (2 * a); else { T s1 = -b + d; if (s1 >= 0) t = s1 / (2 * a); } } else if (a < 0) { T s0 = -b + d; if (s0 <= 0) t = s0 / (2 * a); else { T s1 = -b - d; if (s1 <= 0) t = s1 / (2 * a); } } if (max_time >= 0 && t > max_time) return -1; else return t; }
/** * Add a new set of update vectors to the history. * * @param yk Difference between the current and previous gradient vector. * @param sk Difference between the current and previous state vector. * @param reset Whether to reset the approximation, forgetting about * previous values. * @return In the case of a reset, returns the optimal scaling of the * initial Hessian * approximation which is useful for predicting step-sizes. **/ inline Scalar update(const VectorT &yk, const VectorT &sk, bool reset = false) { Scalar skyk = yk.dot(sk); Scalar B0fact; if (reset) { B0fact = yk.squaredNorm()/skyk; _buf.clear(); } else { B0fact = 1.0; } // New updates are pushed to the "back" of the circular buffer Scalar invskyk = 1.0/skyk; _gammak = skyk/yk.squaredNorm(); _buf.push_back(); _buf.back() = boost::tie(invskyk, yk, sk); return B0fact; }
/** * Get the signed distance of a given point from the hyperplane. This is positive if the point is on the side of the * hyperplane containing the normal, and negative if the point is on the other side. */ T signedDistance(VectorT const & p) const { return p.dot(normal) - dist; }