public override bool HitTest(Ray3 ray, out double t) { ray = ray.Transform(InvPosition); double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; double x0 = ray.Position.X; double y0 = ray.Position.Y; double z0 = ray.Position.Z; double a = dx * dx * dx * dx + dy * dy * dy * dy + dz * dz * dz * dz; double b = 4.0 * dx * dx * dx * x0 + 4.0 * dy * dy * dy * y0 + 4.0 * dz * dz * dz; double c = 6.0 * dx * dx * x0 * x0 - 5.0 * dx * dx + 6.0 * dy * dy * y0 * y0 - 5.0 * dy * dy + 6.0 * dz * dz * z0 * z0 - 5.0 * dz * dz; double d = 4.0 * dx * x0 * x0 * x0 - 10.0 * dx * x0 + 4.0 * dy * y0 * y0 * y0 - 10.0 * dy * y0 + 4.0 * dz * z0 * z0 * z0; double e = x0 * x0 * x0 * x0 - 5.0 * x0 * x0 + y0 * y0 * y0 * y0 - 5.0 * y0 * y0 + z0 * z0 * z0 * z0 - 5.0 * z0 * z0 + 11.8; RealPolynomial poly = new RealPolynomial(a, b, c, d, e); //poly /= new RealPolynomial(100000); //poly.Normalize(); double ev = poly.Eval(1.0); double[] cof = poly.FindRoots(MathUtil.Epsilon, false); //double[] cof=RealPolynomial.SolveQuartic(a, b, c, d, e); bool found = false; t = double.MaxValue; foreach (var tt in RealPolynomial.SolveQuadric(a, b, c)) { if (tt > 1e-4 && tt < t) { t = tt; found = true; } } return(found); }
private static double[] GetRealRoots(double c3, double c2, double c1, double c0) { RealPolynomial rp = new RealPolynomial(c3, c2, c1, c0); return(rp.FindRoots(true)); }
public static Point2d[] EllipseCircle(Ellipse2d el, Circle2d ci) { Transform2d tr = el.ToStandardPosition; ci = new Circle2d(ci); //dont modify original circle, but this copy ci.Transform(tr); double b = el.Ratio, b2 = b * b, b4 = b2 * b2; double i = ci.Center.X, i2 = i * i, i4 = i2 * i2; double j = ci.Center.Y, j2 = j * j, j4 = j2 * j2; double r = ci.Radius, r2 = r * r, r4 = r2 * r2; double x4 = b4 - 2 * b2 + 1; double x3 = 4 * b2 * i - 4 * i; double x2 = b2 * (2 * r2 + 2 * j2 - 2 * i2 + 2) - 2 * r2 + 2 * j2 + 6 * i2 - 2 * b4; double x1 = 4 * i * r2 - 4 * i * j2 - 4 * i * i * i - 4 * b2 * i; double x0 = r4 + (-2 * j2 - 2 * i2) * r2 + b2 * (-2 * r2 - 2 * j2 + 2 * i2) + j4 + 2 * i2 * j2 + i4 + b4; //double[] xs = RealPolynomial.SolveQuartic2(x4, x3, x2, x1, x0, 1e-30); RealPolynomial rp = new RealPolynomial(x4, x3, x2, x1, x0); double[] xs = rp.FindRoots(true); if (xs == null) { return(null); //no intersections } Point2dSet resultset = new Point2dSet(); foreach (double x in xs) { //test the two possible y:s to be solutions for this x double y = (1 - x * x) * b2; if (y < 0.0) { continue; } y = Math.Sqrt(y); for (int t = 0; t < 2; t++) //test booth y solutions... { double err = x * x + y * y / b2 - 1.0; //on ellipse double err2 = MathUtil.Square(x - i) + MathUtil.Square(y - j) - r2; //on circle if (MathUtil.IsZero(err, 1e-7) && MathUtil.IsZero(err2, MathUtil.Epsilon)) { resultset.Add(new Point2d(x, y)); } y = -y; // ...by inverting y in second turn } } if (resultset.Count == 0) { return(null); } resultset.Transform(tr.Inversed); //back to original position return(resultset.ToArray()); }
public override bool HitTest(Ray3 ray, out double t) { ray = ray.Transform(InvPosition); double x0 = ray.Position.X; double y0 = ray.Position.Y; double z0 = ray.Position.Z; double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; double A = x0 * x0 + y0 * y0 + z0 * z0; double B = 2 * (x0 * dx + y0 * dy + z0 * dz); double R2 = R * R; double r2 = r * r; double t4 = A * A; double t3 = 2 * A * B; double t2 = 2 * A * R2 + B * B + 2 * A * A - 2 * r2 * A; double t1 = 2 * B * (R2 + A - r2); double t0 = (2 * A - 2 * r2) * R2 + A * A - 2 * r2 * A + r2 * r2; t2 -= 4 * R2 * (dx * dx + dy * dy); t1 -= 8 * R2 * (dx * x0 + dy * y0); t0 -= 4 * R2 * (x0 * x0 + y0 * y0); RealPolynomial rp = new RealPolynomial(t4, t3, 2, t1, t0); //rp.Normalize(); double[] roots = rp.FindRoots(); /* * * Vector3 p = ray.Position.ToVector(); * Vector3 d = ray.Direction; * * double alpha = d.Dot(d); * double beta = 2.0 * p.Dot(d); * double gamma = p.Dot(p) - tubeRadius*tubeRadius - centralRadius*centralRadius; * * // quatric coefficients * double a4 = alpha*alpha; * double a3 = 2.0 * alpha * beta; * double a2 = beta*beta + (2.0 * alpha * gamma) + (4.0 * centralRadius*centralRadius * d.Z*d.Z); * double a1 = (2.0 * beta * gamma) + (8 * centralRadius*centralRadius * p.Z * d.Z); * double a0 = gamma*gamma + (4.0 * centralRadius*centralRadius * p.Z*p.Z) - (4.0 * centralRadius*centralRadius * tubeRadius*tubeRadius); * * // solve polynomial * double[] roots = RealPolynomial.SolveQuartic(a4, a3, a2, a1, a0); */ bool found = false; t = double.MaxValue; foreach (var tt in roots) { if (tt > 1e-4 && tt < t) { t = tt; found = true; } } return(found); }