homebase - 2 months ago 5x
C++ Question

# How to adjust the size of an ellipse so it always touches a left and right boundary?

I am using the c++ code below to calculate 360 points around the outside of an ellipse which I draw on a canvas. I set the size of the ellipse by selecting a left and right edge as x1, y1, x2, y2. When the ellipse is calculated with a horizontal major axis which is zero degrees the ellipse touches the left and right edge. When I calculate the ellipse with a 45 degree major axis the top and bottom of the ellipse no longer touch the left and right edges. I need to draw the ellipse at an angle so it touches the left and right boundary. To do this I need to draw the ellipse larger but I do not know how to calculate the larger size. Is there a way to calculate the larger size ellipse so the angled ellipse will touch the original left and right boundaries?

``````double x1=0, y1=0, x2=0, y2=0, x3=0, y3=0, phi=0;
int ZeroX=0, ZeroY=0;
int NUM_POINTS_PER_CONTOUR = 360;
int p=0;
int Major_Axis_Center_X=0, Full_Major_Axis_X=0;
int Major_Axis_Center_Y=0, Full_Major_Axis_Y=0;
int Full_Minor_Axis_X=0;
double AngleOfMajorAxis=0;
UnicodeString temp;

struct ell {
double a; //e.a is semi-major size
double b; //e.b is semi-minor size
double theta;
double x0;  //major axis center X
double y0;  //major axis center Y
} e;

//seed Values
x1=50; x2=250;
y1=75; y2=275;

//Vertical Line LEFT edge
Canvas->MoveTo(x1, y1);
Canvas->LineTo(x1, y2);

//Vertical Line RIGHT edge
Canvas->MoveTo(x2, y1);
Canvas->LineTo(x2, y2);

Full_Major_Axis_X   = (x2 - x1);
Full_Major_Axis_Y   = (y2 - y1);
Major_Axis_Center_X = (x1 + (Full_Major_Axis_X/2));
Major_Axis_Center_Y = (y2 - (Full_Major_Axis_Y/2));
Full_Minor_Axis_X   = (Full_Major_Axis_X/2);

//Seed values
e.a = (Full_Major_Axis_X/2); //e.a is semi-major size
e.b = (Full_Minor_Axis_X/2); //e.b is semi-minor size
e.x0 = Major_Axis_Center_X;
e.y0 = Major_Axis_Center_Y;

AngleOfMajorAxis = 45.0;

//Calculate 360 points around edge of ellipse
for (p=0; p<NUM_POINTS_PER_CONTOUR; p++) {
phi = p*2*M_PI/(double)NUM_POINTS_PER_CONTOUR;
x1 = e.a * std::sin(phi);
y1 = e.b * std::cos(phi);
x2 = x1 * std::cos(e.theta) + y1 * std::sin(e.theta);
y2 = y1 * std::cos(e.theta) - x1 * std::sin(e.theta);
x3 = x2 + e.x0;
y3 = y2 + e.y0;
if(p==0){
Canvas->MoveTo(x3, y3);
}
Canvas->LineTo(x3, y3);
}
``````

EDIT: Here is the best answer

I have added the two lines of code above my for loop

``````phiMax =  atan(e.b/e.a * std::tan(e.theta));   //   {1}
Coeff = e.a / (e.a * std::cos(phiMax) * std::cos(e.theta) + e.b * std::sin(phiMax) * std::sin(e.theta));  // {2}
``````

Now I add the Coeff into the for loop

``````//Calculate 360 points around edge of ellipse
for (p=0; p<NUM_POINTS_PER_CONTOUR; p++) {
phi = p*2*M_PI/(double)NUM_POINTS_PER_CONTOUR;
x1 = Coeff * e.a * std::sin(phi);
y1 = Coeff * e.b * std::cos(phi);
x2 = x1 * std::cos(e.theta) + y1 * std::sin(e.theta);
y2 = y1 * std::cos(e.theta) - x1 * std::sin(e.theta);
x3 = x2 + e.x0;
y3 = y2 + e.y0;
if(p==0){
Canvas->MoveTo(x3, y3);
}
Canvas->LineTo(x3, y3);
}
``````

The result is that the widest part of the ellipse always touches the left and right boundary. This is the simplest and closest answer. The picture below shows a 65 degree ellipse adjusted to touch the boundaries.

Ellipse centered at `(0,0)`, rotated by `t` (your `theta`), has equation for x-coordinate

``````x = a * cos(phi) * cos(t) + b * sin(phi) * sin(t)
``````

Extremal points (left and right) are reached when derivative is zero `x'=0`

``````dx/dphi = - a * sin(phi) * cos(t) +  b * cos(phi) * sin(t) = 0
a * sin(phi) * cos(t) =  b * cos(phi) * sin(t)
tg(phi) = b/a * tg(t)
phiMax =  atan(b/a * tg(t))      {1}
``````

Substitute this value in the first equation and find coefficient for enlargement (extremal semi-size should be equal to the semi-axis)

``````Coeff * (a * cos(phiMax) * cos(t) + b * sin(phiMax) * sin(t)) = a
Coeff = a / (a * cos(phiMax) * cos(t) + b * sin(phiMax) * sin(t))   {2}
``````

Now you can implement formulas `{1}` and `{2}` and use this coefficient in your calculations like this:

``````x1 = Coeff * e.a * std::sin(phi);
y1 = Coeff * e.b * std::cos(phi);
``````