import java.io.PrintStream; import java.text.DecimalFormat; import java.util.Arrays; import java.util.Scanner; /** * Solution to Ellipse Eclipse * * @author vanb */ public class ellipse_vanb { /** Input. */ private static Scanner sc; /** Output. */ private static PrintStream ps; /** * Do it! */ private void doit() { double x1 = sc.nextDouble(); double y1 = sc.nextDouble(); double x2 = sc.nextDouble(); double y2 = sc.nextDouble(); double a = sc.nextDouble(); // First of all, semimajor is more useful than major a = a/2.0; // The center of the ellipse is exactly mid way between the foci double cx = (x1+x2)/2.0; double cy = (y1+y2)/2.0; // We'll need the semiminor. This'll take some explanation. // An ellipse is the set of all points where the sum of the distances from each point to the two foci is constant. // It turns out that that distance is exactly the length of the major axis. // OK, now look at a point on the minor axis. The length of the semiminor will be the distance from that point to the center. // It forms a right triangle with one of the foci. The distance from a foci to that point is exactly the semimajor! // The sum of the distances from that point to the two foci is the length of the major axis. // It's symmetrical, so the distance to one of the foci is the semimajor. // OK, now we've got a right triangle with the semimajor as the hypotenuse, the distance from the center to a focus as one leg, // and the semiminor as the other leg. Pythagorus!! double dx = cx-x1; double dy = cy-y1; double d = Math.sqrt( dx*dx + dy*dy ); double b = Math.sqrt( a*a - d*d ); // Our ellipse is rotated by alpha. cos and sin of alpha will be useful! double alpha = -Math.atan2( y2-y1, x2-x1 ); double cosa = Math.cos( alpha ); double sina = Math.sin( alpha ); // OK, more heavy math here. Assume the ellipse's center is at the origin (Yeah, I know it isn't - bear with me.) // The points of the ellipse can be expressed parametrically as: x = a*cos(theta), y = b*sin(theta) // But, we're rotated by alpha. To rotate (x,y) around the origin by alpha, it's: // x' = x*cos(alpha) - y*sin(alpha) // y' = x*sin(alpha) + y*cos(alpha) // So, plugging in our parametric representation of the ellipse, // x' = a*cos(theta)*cos(alpha) - b*sin(theta)sin(alpha) // y' = a*cos(theta)*sin(alpha) + b*sin(theta)cos(alpha) // Now, things get REALLY messy. The only variable here is theta. If we take the derivative with respect to theta, // and set that equal to 0, we can find the inflection points - maximums and minimums - which is exactly what we're looking for! // We'll do x and leave y to you. Remember that the derivative of cos is -sin, and the derivative of sin is cos. // d/dtheta a*cos(theta)*cos(alpha) - b*sin(theta)sin(alpha) // = -a*sin(theta)*cos(alpha) - b*cos(theta)sin(alpha) = 0 // a*sin(theta)*cos(alpha) = -b*cos(theta)sin(alpha) // a*[sin(theta)/cos(theta)]*cos(alpha) = -b*sin(alpha) // a*tan(theta)*cos(alpha) = -b*sin(alpha) // tan(theta) = -b*sin(alpha)/(a*cos(alpha)) // theta = atan2( -b*sin(alpha), a*cos(alpha) ) // Now, with theta, we can just plug it back in to the parametric representation of x. // That tells us distance from the origin - on either side, since it's symmetrical. // So, we can just add & subtract the absolute value of that from our center x to get x_low and x_high double theta = Math.atan2( -b*sina, a*cosa ); dx = Math.abs( a*Math.cos(theta)*cosa - b*Math.sin(theta)*sina ); double xlo = cx - dx; double xhi = cx + dx; // We pull the same trick for y. You can do the math yourself. theta = Math.atan2( b*cosa, a*sina ); dy = Math.abs( a*Math.cos(theta)*sina + b*Math.sin(theta)*cosa ); double ylo = cy - dy; double yhi = cy + dy; DecimalFormat df = new DecimalFormat( "0.000000" ); ps.println( df.format( xlo ) + " " + df.format( ylo ) + " " + df.format( xhi ) + " " + df.format( yhi ) ); } /** * Main. * * @param args unused * @throws Exception */ public static void main( String[] args ) throws Exception { sc = new Scanner( System.in ); ps = System.out; new ellipse_vanb().doit(); } }