public static Point2d[] HyperbolaEllipse(Hyperbola2d hyp, Ellipse2d elp) { //TODO: this is probably more stable intersecting hyperbola with unitcircle. Rewrite. Transform2d tr = hyp.ToStandardPosition; hyp = new Hyperbola2d(hyp); elp = new Ellipse2d(elp); hyp.Transform(tr); elp.Transform(tr); GeneralConic2d hcon = new GeneralConic2d(1, 0.0, -1 / (hyp.B * hyp.B), 0.0, 0.0, -1); Point2dSet pset = new Point2dSet(); pset.AddRange(ConicConic(hcon, elp.ToGeneralConic())); pset.Transform(tr.Inversed); return(pset.ToArray()); }
public static Point2d[] EllipseEllipse2(Ellipse2d elp1, Ellipse2d elp2) { //TODO: check if this is better than EllipseEllipse in stabillity and replace it or remove this function Transform2d tr = elp1.ToStandardPosition; elp2 = new Ellipse2d(elp2); //dont alter the original ellipse elp2.Transform(tr); elp1 = new Ellipse2d(elp1); elp1.Transform(tr); GeneralConic2d con1 = new GeneralConic2d(1.0, 0.0, 1 / (elp1.Ratio * elp1.Ratio), 0.0, 0.0, -1.0); GeneralConic2d con2 = elp2.ToGeneralConic(); // GeneralConic2d.FromEllipse(elp2); Point2dSet pset = new Point2dSet(); pset.AddRange(ConicConic(con1, con2)); pset.Transform(tr.Inversed); return(pset.ToArray()); }
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()); }
/// <summary> /// Returns all the perpendicular points on the ellipse from a given point 'from' /// </summary> public Point2d[] Perpendicular(Point2d from) { // Solved by Robert.P. in december 2012 // Note on solutions: // Quartic coefficients gotten from applying lagrange multiplier to minimize (x-i)^2+(y-j)^2 // with x^2/a^2+y^2/b^2-1=0 as constraint (a=1 because we work in standard position). // This gives a system of three equations F_x,F_y,F_lambda, which were solved with // resultant theory using 'eliminate' in maxima //work in standard position, retranslate solutions last Transform2d tostd = ToStandardPosition; from = from.GetTransformed(tostd); double b = sigratio, b2 = b * b, b4 = b2 * b2; double i = from.X, i2 = i * i; double j = from.Y, j2 = j * j; double x4 = b4 - 2 * b2 + 1; double x3 = 2 * b2 * i - 2 * i; double x2 = b2 * j2 + i2 - b4 + 2 * b2 - 1; double x1 = 2 * i - 2 * b2 * i; double x0 = -i2; double[] sols = RealPolynomial.SolveQuartic2(x4, x3, x2, x1, x0, 1e-16); if (sols == null) { return(null); } Point2dSet respts = new Point2dSet(); foreach (double x in sols) { double y = (1 - x * x) * b2; if (y < 0.0) { continue; } y = Math.Sqrt(y); for (int l = 0; l < 2; l++) { //both posetive and negative y:s can be solutions. Check with each possible //point that its perpendicular to ellipse (subtracting the inverse ellipse slope (=normal slope) with the slope from 'from' point) double err; err = y * (from.X - x) - x * b2 * (from.Y - y); if (Math.Abs(err) < 1e-6) { respts.Add(new Point2d(x, y)); } y = -y; //test negative solution as well } } respts.Transform(tostd.Inversed); return(respts.ToArray()); }