# L-33 MCS 260 Monday 6 April 2015 : class_parabola
"""
Given a point (the focus) and a line (the directrix),
a parabola consists of all points that lie as far from
the focus as from the directrix.
The directrix is inherited from the class Line and
the focus is the other data attribute.
"""
from class_point import Point
from class_line import Line

class Parabola(Line):
    """
    A parabola is defined by a line,
    its directrix and a point, its focus.
    """
    def __init__(self, px, py, agl, fx, fy):
        """
        Defines the line at (px, py)
        and angle agl and focus (fx, fy).
        """
        Line.__init__(self, px, py, agl)
        self.focus = Point(fx, fy)

    def __str__(self):
        """
        Returns the string representation.
        """
        strfocus = str(self.focus)
        line = Line.__str__(self)
        result = 'focus : ' + strfocus
        result += ', directrix : ' + line
        return result

    def __call__(self, t):
        """
        Returns a point on the parabola
        as far from the focus and the point
        obtained by evaluating the directrix.
        """
        line = Line.__call__(self, t)
        (fcx, fcy) = (self.focus.xpt, self.focus.ypt)
        disc = 2*(fcx - line.xpt)*(line.ypt - self.ypt) \
             - 2*(fcy - line.ypt)*(line.xpt - self.xpt)
        rh1 = fcx**2 + fcy**2 - line.xpt**2 - line.ypt**2
        if disc + 1.0 != 1.0:
            rh2 = line.xpt*(line.xpt - self.xpt) \
                + line.ypt*(line.ypt - self.ypt)
            sdx = (rh1*(line.ypt - self.ypt) \
                - 2*rh2*(fcy - line.ypt))/float(disc)
            sdy = (2*(fcx - line.xpt)*rh2 \
                - (line.xpt - self.xpt)*rh1)/float(disc)
        else:
            from math import exp, pi
            line = Line.__call__(self, exp(pi))
            disc = 2*(fcx - line.xpt)*(line.ypt - self.ypt) \
                 - 2*(fcy - line.ypt)*(line.xpt - self.xpt)
            rh1 = fcx**2 + fcy**2 - line.xpt**2 - line.ypt**2
            rh2 = line.xpt*(line.xpt - self.xpt) \
                + line.ypt*(line.ypt - self.ypt)
            sdx = (rh1*(line.ypt - self.ypt) \
                - 2*rh2*(fcy - line.ypt))/float(disc)
            sdy = (2*(fcx - line.xpt)*rh2 \
                - (line.xpt - self.xpt)*rh1)/float(disc)
        return Point(sdx, sdy)

def main():
    """
    Instantiates a parabola and evaluates.
    """
    print('instantiating a parabola ...')
    prb = Parabola(3, 4, -1.23, 10, 0)
    print(prb)
    point = prb(4)
    print('a point on the parabola :', point)

if __name__ == "__main__":
    main()
