# Path: retina/screen/map/pointmap.py
# class PointMapWithDirection(object):
#     """ Interface of mapping a point from one surface to another
#         (hence the 2 parameters)
#     """
#     __metaclass__ = ABCMeta
# 
#     @abstractmethod
#     def map(self, p1, p2, dp1, dp2):
#         """ map of point (p1, p2) from one surface to another
#             in direction (dp1, dp2) """
#         return
# 
#     @abstractmethod
#     def invmap(self, p1, p2, dp1, dp2):
#         """ inverse map of point (p1, p2) from one surface to another
#             in direction (dp1, dp2) """
#         return


import numpy as np
from .pointmap import PointMapWithDirection
        # Solving
        # ||x + l*dx||_2 = r2
        a = 1
        b = x1*dx1 + y1*dy1 + z1*dz1
        c = r1*r1 - r2*r2

        l = solve_quadratic(a, b, c).reshape(result_shape)

        x2 = x1 + l*dx1
        y2 = y1 + l*dy1
        z2 = z1 + l*dz1

        map_elev = np.arcsin(z2/r2)
        map_azim = np.arctan2(-y2, -x2)

        try:
            return (map_elev.reshape(result_shape),
                    map_azim.reshape(result_shape))
        except AttributeError:  # if elev and azim scalars
            return (np.asscalar(map_elev), np.asscalar(map_azim))

    def map(self, elev, azim, delev, dazim):
        return self.map_aux(elev, azim, delev, dazim,
                            self._r1, self._r2)

    def invmap(self, elev, azim, delev, dazim):
        return self.map_aux(elev, azim, delev, dazim,
                            self._r2, self._r1)



# Path: retina/screen/map/pointmap.py
# class PointMapWithDirection(object):
#     """ Interface of mapping a point from one surface to another
#         (hence the 2 parameters)
#     """
#     __metaclass__ = ABCMeta
# 
#     @abstractmethod
#     def map(self, p1, p2, dp1, dp2):
#         """ map of point (p1, p2) from one surface to another
#             in direction (dp1, dp2) """
#         return
# 
#     @abstractmethod
#     def invmap(self, p1, p2, dp1, dp2):
#         """ inverse map of point (p1, p2) from one surface to another
#             in direction (dp1, dp2) """
#         return


# Path: retina/screen/map/mapimpldr.py
import numpy as np
from .pointmap import PointMapWithDirection

        # Solving
        # ||x + l*dx||_2 = r2
        a = 1
        b = x1*dx1 + y1*dy1 + z1*dz1
        c = r1*r1 - r2*r2

        l = solve_quadratic(a, b, c).reshape(result_shape)

        x2 = x1 + l*dx1
        y2 = y1 + l*dy1
        z2 = z1 + l*dz1

        map_elev = np.arcsin(z2/r2)
        map_azim = np.arctan2(-y2, -x2)

        try:
            return (map_elev.reshape(result_shape),
                    map_azim.reshape(result_shape))
        except AttributeError:  # if elev and azim scalars
            return (np.asscalar(map_elev), np.asscalar(map_azim))

    def map(self, elev, azim, delev, dazim):
        return self.map_aux(elev, azim, delev, dazim,
                            self._r1, self._r2)

    def invmap(self, elev, azim, delev, dazim):
        return self.map_aux(elev, azim, delev, dazim,
                            self._r2, self._r1)



class SphereToCylinderMap(PointMapWithDirection):