Charles Moore
Charles Moore

Reputation: 11

Ellipse construction

I would like to construct an ellipse given the major/minor axes (or radii) and two points. I would like the line between the two points to be on the major axis. This just means that I would like the two points to lie on the major axis, and then construct the ellipse around the major axis. I originally constructed the ellipse at the origin and attempted to rotate and translate the ellipse, which didn't work. The unfinished code I have is listed below. How can I go about constructing an ellipse in this manner? Ideally, this would just return a list. Any insights would be greatly appreciated, and if you have any code for this please feel free to share.

import numpy
import matplotlib.pyplot as plt
import random

import math
from math import sin, cos
# Returns theta in [-pi/2, 3pi/2]
def generate_theta(a, b):
    u = random.random() / 4.0
    theta = numpy.arctan(b/a * numpy.tan(2*numpy.pi*u))

    v = random.random()
    if v < 0.25:
        return theta
    elif v < 0.5:
        return numpy.pi - theta
    elif v < 0.75:
        return numpy.pi + theta
    else:
        return -theta

def radius(a, b, theta):
    return a * b / numpy.sqrt((b*numpy.cos(theta))**2 + (a*numpy.sin(theta))**2)


def random_point(a, b, third_point, center=(0, 0)):
    angle = None
    if a > b:
        random_theta = generate_theta(a, b)
        max_radius = radius(a, b, random_theta)
        random_radius = max_radius * numpy.sqrt(random.random())
        f = round(random_radius * numpy.cos(random_theta))
        s = round(random_radius * numpy.sin(random_theta))
        angle = math.atan2(third_point[1], third_point[0]) - math.atan2(center[1], center[0])
    
    
    else:
        random_theta = generate_theta(b, a)
        max_radius = radius(b, a, random_theta)
        random_radius = max_radius * numpy.sqrt(random.random())
        f = round(random_radius * numpy.cos(random_theta))
        s = round(random_radius * numpy.sin(random_theta))
        
        angle = math.atan2(third_point[1], third_point[0]) - math.atan2(center[1], center[0])

        
    lio = rotate(center, (f, s), angle)
    lio = (int(lio[0]), int(lio[1]))
    return numpy.array([third, ward])



def rotate(origin, point, angle):
        #Rotate a point counterclockwise by a given angle around a given origin.
        #The angle should be given in radians.
        x = origin[0] + cos(angle) * (point[0] - origin[0]) - sin(angle) * (point[1] - origin[1])
        y = origin[1] + sin(angle) * (point[0] - origin[0]) + cos(angle) * (point[1] - origin[1])
        return (x, y)

#height
a = 95
#length
b = 25
#rand_p = (-random.randint(300, 400), -random.randint(100, 300))
rand_p = (0, 0)
points = numpy.array([random_point(a, b, (100, 100), (-25, 0)) for _ in range(200)])
#rando = rotate((0, 0), right_most_point, angle)
iopoints = []
  #  t = x[0] - (int(centroid[0]) - 100)
  #  t2 = x[1] - (int(centroid[1]) - 100)
centroid = numpy.mean(points, axis=0)
print(centroid)


#plt.plot(rando[0], rando[1], 'ro')
plt.plot(rand_p[0], rand_p[1], 'ro')
plt.scatter(points[:,0], points[:,1])

plt.show()


Upvotes: 0

Views: 218

Answers (1)

Charles Moore
Charles Moore

Reputation: 11

class ELLIPSE:
    def __init__(self, a, b, num_points, start, end):
        self.a = a
        self.b = b
        self.num_points = num_points
        self.start = start
        self.end = end
        self.angle_gen = math.atan2(self.end[1]-self.start[1], self.end[0]-self.start[0])
    
    def generate_theta(self, a, b):
            u = random.random() / 4.0
            theta = np.arctan(self.b/self.a * np.tan(2*np.pi*u))

            v = random.random()
            if v < 0.25:
                return theta
            elif v < 0.5:
                return np.pi - theta
            elif v < 0.75:
                return np.pi + theta
            else:
                return -theta

    def radius(self, a, b, theta):
            return self.a * self.b / np.sqrt((b*np.cos(theta))**2 + (a*np.sin(theta))**2)


    def random_point(self, major_axis, minor_axis, center, qa):
            random_theta = self.generate_theta(self.a, self.b)
            max_radius = self.radius(self.a, self.b, random_theta)
            random_radius = max_radius * np.sqrt(random.random())
            f = round(random_radius * np.cos(random_theta))
            s = round(random_radius * np.sin(random_theta))
            lio = self.rotate((0, 0), (f, s), self.angle_gen)
            return (int(lio[0]+center[0]), int(lio[1]+center[1]))


    def rotate(self, origin, point, angle):
            """
            Rotate a point counterclockwise by a given angle around a given origin.

            The angle should be given in radians.
            """
            ox, oy = origin
            px, py = point

            qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy)
            qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy)
            return qx, qy

    def midpoint(self, p1, p2):
            return ((p1[0]+p2[0])/2, (p1[1]+p2[1])/2)

    def ret_list(self):
        points = [self.random_point(self.a, self.b, self.midpoint(self.start, self.end),  self.angle_gen) for _ in range(self.num_points)]
        return points

Upvotes: 1

Related Questions