Prunus Persica
Prunus Persica

Reputation: 1203

Generating ellipse with rotation and semi-major and semi-minor axes

I have the parameters of an eclipse: semi-major axis; semi-minor axis; rotation angle; x-position of the centre of the ellipse; y-position of the centre of the ellipse.

I wish to produce an array whereby all points inside the ellipse are set to one and all points outside are zero.

I found this answer, which gave a solution to this without rotation, and using height and width, rather than semi-major and semi-minor:

import numpy as np
from matplotlib import pyplot as plt

x0 = 4  # x center,
a = 5  #  half width
y0 = 2  # y center,
b = 3  # half height
x = np.linspace(-10, 10, 100)  # x values of interest
y = np.linspace(-5, 5, 100)[:,
                            None]  # y values of interest, as a "column" array
ellipse = ((x - x0) / a)**2 + (
    (y - y0) / b)**2 <= 1  # True for points inside the ellipse

plt.imshow(ellipse, origin="lower")  # Plot

non-rotated ellipse

Thus, I'm looking to modify this code to take the parameters I require. I found a definition of the general equation of an eclipse here

enter image description here

I attempted to reproduce this with this modification:

import numpy as np
from matplotlib import pyplot as plt

x0 = 4  # x center,
a = 5  #  half width
y0 = 2  # y center,
b = 3  # half height
x = np.linspace(-10, 10, 100)  # x values of interest
y = np.linspace(-5, 5, 100)[:,
                            None]  # y values of interest, as a "column" array

def calc_ellipse(x, y, x_centre, y_centre, rotation, semi_major, semi_minor):
    # https://www.maa.org/external_archive/joma/Volume8/Kalman/General.html
    ...
    term1 = ((x - x_centre) * np.cos(rotation)) + (
        (y - y0) * np.sin(rotation))**2
    term2 = ((x - x_centre) * np.sin(rotation)) + (
        (y - y0) * np.cos(rotation))**2
    ellipse = ((term1 / semi_major**2) + (term2 / semi_minor**2)) <= 1
    return ellipse


ellipse = calc_ellipse(x, y, x0, y0, 0, a, b)

plt.imshow(ellipse, origin="lower")  # Plot

enter image description here

However as you can see I end up with a strange shape, even when I set the rotation angle to 0.

This question showed a way of generating an ellipse with a rotation, however the parameters are hard-coded, and thus is not reuseable or easy to interpret.

How would I generate an array like this with the parameters defining the general equation of the eclipse?

Upvotes: 1

Views: 1498

Answers (2)

Kat
Kat

Reputation: 1

Also you've copied the +/- signs wrong. It should be:

term1 = (((x - x_centre) * np.cos(rotation) + 
        (y - y_centre) * np.sin(rotation)))**2
term2 = (((x - x_centre) * np.sin(rotation) -
        (y - y_centre) * np.cos(rotation)))**2

according to what you've posted

Upvotes: 0

Blupper
Blupper

Reputation: 398

In your calc_ellipse function you are missing parenthesis in term1 and term2. To match the formula you've posted it should look like this:

    term1 = (((x - x_centre) * np.cos(rotation)) + (
        (y - y0) * np.sin(rotation)))**2
    term2 = (((x - x_centre) * np.sin(rotation)) + (
        (y - y0) * np.cos(rotation)))**2

Or like this:

    term1 = ((x - x_centre) * np.cos(rotation) + 
        (y - y0) * np.sin(rotation))**2
    term2 = ((x - x_centre) * np.sin(rotation) + 
        (y - y0) * np.cos(rotation))**2

Try those changes and see if it works.

Upvotes: 2

Related Questions