Ellipse

Table Of Contents

Diagram
Using the Ellipse Standard Equation
Using the Ellipse Parametric Equations

Diagram

image missing
Image From: commons.wikimedia.org

Using the Ellipse Standard Equation

#!/usr/bin/python3 # ============================================================== # X,Y points on an ellipse # ============================================================== # # ellipse test case: h = 0, k = 0, a = 2, b = 3, x = 1 # # two possible Y values, approximately 2.60 and -2.60 # # ============================================================= # # the standard equation for an ellipse: # # (x-h)**2 (y-k)**2 # -------- + -------- = 1 # a**2 b**2 # # (h,k) coord (X,Y) of the center of the ellipse # (normally 0,0 for simplicity) # # a semi-major axis (parallel to the plot X axis) # b semi-minor axis (parallel to the plot Y axis) # # code version of the equation: # # y1 = k + math.sqrt(b**2 * (1 - ((x-h)**2)/a**2)) # y2 = k - math.sqrt(b**2 * (1 - ((x-h)**2)/a**2)) # # ============================================================== # # Definition: # # The semi-major axis is the line segment from the center # of the ellipse to one of its vertices along the longest # axis. It is exactly half the length of the major axis, # which is the ellipse's longest diameter. # # ============================================================== import coordinate_conversion as cc import graphics as gr import math # -------------------------------------------------------------- # ---- ellipse class # -------------------------------------------------------------- class Ellipse(): # ---- initialize def __init__(self, semi_axis_a, semi_axis_b, h=0.0, k=0.0): self.a = semi_axis_a self.b = semi_axis_b self.h = h self.k = k # ---- calculate an ellipse's y values given a x value def y(self,x): y1 = k + math.sqrt(self.b**2 * \ (1 - ((x-self.h)**2)/self.a**2)) y2 = k - math.sqrt(self.b**2 * \ (1 - ((x-self.h)**2)/self.a**2)) return(y1,y2) # ---- display the ellipse internals def display(self,title='ellipse'): print() print(title) print(f'a = {self.a}') print(f'b = {self.b}') print(f'h = {self.h}') print(f'k = {self.k}') print() # -------------------------------------------------------------- # ---- draw a point (small circle) # -------------------------------------------------------------- def draw_point(win, x, y): # ---- convert Cartesian to window coordinates wx,wy = cc.center_to_win_coords(x,y,win.width,win.height) # ---- draw small circle c = gr.Circle(gr.Point(wx,wy),4) c.setOutline('black') c.setWidth(1) c.setFill('red') c.draw(win) # -------------------------------------------------------------- # ---- create graphics window/canvas # -------------------------------------------------------------- def create_graphics_window(title, width=401, height=401): # ---- graphics window/canvas win = gr.GraphWin('Draw Ellipse', width, height) win.setBackground('white') wintop = gr.Line(gr.Point(0,0), gr.Point(width-1,0)) wintop.setWidth(1) wintop.setFill('black') wintop.draw(win) # ---- X axis xax = gr.Line(gr.Point(0,width/2), gr.Point(width-1, height/2)) xax.setWidth(1) xax.setFill('black') xax.draw(win) # ---- Y axis yax = gr.Line(gr.Point(width/2, 0), gr.Point(width/2, height-1)) yax.setWidth(1) yax.setFill('black') yax.draw(win) return win # -------------------------------------------------------------- # ---- draw an ellipse # ---- a is assumed to be the plot X axis # ---- b is assumed to be the plot Y axis # -------------------------------------------------------------- def draw_ellipse(ellip:Ellipse): a = ellip.a b = ellip.b h = ellip.h k = ellip.k win = create_graphics_window('Draw Ellipse') # ---- draw ellipse X,Y coordinates for x in range(0,round(a+1),10): # ---- stay inside the X plot range # ---- outside is an error (use try...catch?) if x > ellip.a: print(f'skipping x = {x}') continue # ---- draw ellipse (note: y=0 is drawn twice) y1,y2 = ellip.y(x) draw_point(win,x,y1) draw_point(win,x,y2) draw_point(win,-x,y1) draw_point(win,-x,y2) # ---- wait to stop the program win.getMouse() win.close() # -------------------------------------------------------------- # ---- test ellipse X,Y coordinate equation # -------------------------------------------------------------- def test_ellipse_equation(x,a,b,h=0.0,k=0.0): # ---- use the equations y1 = k + math.sqrt(b**2 * (1-((x-h)**2)/a**2)) y2 = k - math.sqrt(b**2 * (1-((x-h)**2)/a**2)) print(f'x = {x}, y1 = {y1}') print(f'x = {x}, y2 = {y2}') # ---- use my ellipse class/object elip = Ellipse(a,b) print(f'ellipse: y = {elip.y(x)}') # -------------------------------------------------------------- # ---- main # -------------------------------------------------------------- if __name__ == '__main__': # ---- test a = 2 # semi-axis (x axis) b = 3 # semi-axis (y axis) h = 0 # ellipse center X coord k = 0 # ellipse center Y coord print() print('-'*50) test_ellipse_equation(1,a,b) print() test_ellipse_equation(1,1.5,b) print() test_ellipse_equation(2,a,b) ##print() ##test_ellipse_equation(3,a,b) print('-'*50) # ---- using the ellipse class/object, draw an ellipse a = 100 # semi-major axis (plot X axis) b = 50 # semi-minor axis (plot Y axis) h = 0 # ellipse center X coord k = 0 # ellipse center Y coord ellip = Ellipse(a,b) ellip.display('testing the ellipse class') draw_ellipse(ellip)

More Information on the ellipse equation.

image missing

Using the Ellipse Parametric Equations

The coordinates of any point on the ellipse can be generated using the parametric equations:

x = h + a * cos(t)

y = k + b * sin(t)

(h,k) is the center of the ellipse
a is the length of the semi-axis length along the X axis
b is the length of the semi-axis length along the Y axis
t is a parameter (angle) that ranges from 0 to 2π radians (0° to 360°)

#!/usr/bin/python3 # ============================================================== # ellipse X,Y values # ============================================================== # # ellipse parametric equations # # x = h + a * cos(t) # # y = k + b * sin(t) # # (h,k) is the center of the ellipse # # a is the semi-axis length along the x-direction # b is the semi-axis length along the y-direction # t is a parameter that ranges from 0 to 2π radians # (0° to 360°) # # ============================================================== # # Definition: # # The semi-major axis is the line segment from the center # of the ellipse to one of its vertices along the longest # axis. It is exactly half the length of the major axis, # which is the ellipse's longest diameter. # # ============================================================== import coordinate_conversion as cc import graphics as gr import math # -------------------------------------------------------------- # ---- ellipse class # -------------------------------------------------------------- class EllipseParametric(): # ---- initialize def __init__(self, semi_axis_a, semi_axis_b, h=0, k=0): self.a = semi_axis_a self.b = semi_axis_b self.h = h self.k = k # ---- calculate an ellipse's x,y coordinates # ---- given an angle in degrees def xy(self,deg): rad = math.radians(deg) x = self.h + self.a * math.cos(rad) y = self.k + self.b * math.sin(rad) return(x,y) # ---- display the ellipse internals def display(self,title='Ellipse (Parametric)'): print() print(title) print(f'a = {self.a}') print(f'b = {self.b}') print(f'h = {self.h}') print(f'k = {self.k}') print() # -------------------------------------------------------------- # ---- draw a point (small circle) # -------------------------------------------------------------- def draw_point(win, x, y): # ---- convert Cartesian to window coordinates wx,wy = cc.center_to_win_coords(x,y,win.width,win.height) # ---- draw small circle c = gr.Circle(gr.Point(wx,wy),4) c.setOutline('black') c.setWidth(1) c.setFill('red') c.draw(win) # -------------------------------------------------------------- # ---- create graphics window/canvas # -------------------------------------------------------------- def create_graphics_window(title, width=401, height=401): # ---- graphics window/canvas win = gr.GraphWin('Draw Ellipse', width, height) win.setBackground('white') wintop = gr.Line(gr.Point(0,0), gr.Point(width-1,0)) wintop.setWidth(1) wintop.setFill('black') wintop.draw(win) # ---- X axis xax = gr.Line(gr.Point(0,width/2), gr.Point(width-1, height/2)) xax.setWidth(1) xax.setFill('black') xax.draw(win) # ---- Y axis yax = gr.Line(gr.Point(width/2, 0), gr.Point(width/2, height-1)) yax.setWidth(1) yax.setFill('black') yax.draw(win) return win # -------------------------------------------------------------- # ---- draw an ellipse # ---- a is assumed to be the plot X axis # ---- b is assumed to be the plot Y axis # -------------------------------------------------------------- def draw_ellipse_parametric(ellip): a = ellip.a b = ellip.b h = ellip.h k = ellip.k win = create_graphics_window('Parametric Equations Ellipse') # ---- draw ellipse X,Y coordinates for deg in range(0,360,10): x,y = ellip.xy(deg) draw_point(win,x,y) # ---- wait to stop the program win.getMouse() win.close() # -------------------------------------------------------------- # ---- main # -------------------------------------------------------------- if __name__ == '__main__': # ---- using the ellipse class/object, draw an ellipse a = 150 # semi-major axis (plot X axis) b = 100 # semi-minor axis (plot Y axis) h = 0 # ellipse center X coord k = 0 # ellipse center Y coord ellip = EllipseParametric(a,b) ellip.display('testing the (parametric) ellipse class') draw_ellipse_parametric(ellip)

Add to the above code

function draw_point - optionally draw a point with a different color and width.

function draw_ellipse - optionally draw a point at the center of the ellipse (different color and width).