示例#1
0
    def tangent_lines(self, p):
        """Tangent lines between `p` and the ellipse.

        If `p` is on the ellipse, returns the tangent line through point `p`.
        Otherwise, returns the tangent line(s) from `p` to the ellipse, or
        None if no tangent line is possible (e.g., `p` inside ellipse).

        Parameters
        ==========

        p : Point

        Returns
        =======

        tangent_lines : list with 1 or 2 Lines

        Raises
        ======

        NotImplementedError
            Can only find tangent lines for a point, `p`, on the ellipse.

        See Also
        ========

        sympy.geometry.point.Point, sympy.geometry.line.Line

        Examples
        ========

        >>> from sympy import Point, Ellipse
        >>> e1 = Ellipse(Point(0, 0), 3, 2)
        >>> e1.tangent_lines(Point(3, 0))
        [Line(Point(3, 0), Point(3, -12))]

        >>> # This will plot an ellipse together with a tangent line.
        >>> from sympy.plotting.pygletplot import PygletPlot as Plot
        >>> from sympy import Point, Ellipse
        >>> e = Ellipse(Point(0,0), 3, 2)
        >>> t = e.tangent_lines(e.random_point())
        >>> p = Plot()
        >>> p[0] = e # doctest: +SKIP
        >>> p[1] = t # doctest: +SKIP

        """
        if self.encloses_point(p):
            return []

        if p in self:
            delta = self.center - p
            rise = (self.vradius ** 2)*delta.x
            run = -(self.hradius ** 2)*delta.y
            p2 = Point(simplify(p.x + run),
                       simplify(p.y + rise))
            return [Line(p, p2)]
        else:
            if len(self.foci) == 2:
                f1, f2 = self.foci
                maj = self.hradius
                test = (2*maj -
                        Point.distance(f1, p) -
                        Point.distance(f2, p))
            else:
                test = self.radius - Point.distance(self.center, p)
            if test.is_number and test.is_positive:
                return []
            # else p is outside the ellipse or we can't tell. In case of the
            # latter, the solutions returned will only be valid if
            # the point is not inside the ellipse; if it is, nan will result.
            x, y = Dummy('x'), Dummy('y')
            eq = self.equation(x, y)
            dydx = idiff(eq, y, x)
            slope = Line(p, Point(x, y)).slope
            tangent_points = solve([slope - dydx, eq], [x, y])

            # handle horizontal and vertical tangent lines
            if len(tangent_points) == 1:
                assert tangent_points[0][
                    0] == p.x or tangent_points[0][1] == p.y
                return [Line(p, p + Point(1, 0)), Line(p, p + Point(0, 1))]

            # others
            return [Line(p, tangent_points[0]), Line(p, tangent_points[1])]
示例#2
0
文件: ellipse.py 项目: Narsil/sympy
    def tangent_lines(self, p):
        """Tangent lines between `p` and the ellipse.

        If `p` is on the ellipse, returns the tangent line through point `p`.
        Otherwise, returns the tangent line(s) from `p` to the ellipse, or
        None if no tangent line is possible (e.g., `p` inside ellipse).

        Parameters
        ----------
        p : Point

        Returns
        -------
        tangent_lines : list with 1 or 2 Lines

        Raises
        ------
        NotImplementedError
            Can only find tangent lines for a point, `p`, on the ellipse.

        See Also
        --------
        Point
        Line

        Examples
        --------
        >>> from sympy import Point, Ellipse
        >>> e1 = Ellipse(Point(0, 0), 3, 2)
        >>> e1.tangent_lines(Point(3, 0))
        [Line(Point(3, 0), Point(3, -12))]

        >>> # This will plot an ellipse together with a tangent line.
        >>> from sympy import Point, Ellipse, Plot
        >>> e = Ellipse(Point(0,0), 3, 2)
        >>> t = e.tangent_lines(e.random_point()) # doctest: +SKIP
        >>> p = Plot() # doctest: +SKIP
        >>> p[0] = e # doctest: +SKIP
        >>> p[1] = t # doctest: +SKIP

        """
        from sympy import solve

        if self.encloses_point(p):
            return []

        if p in self:
            rise = (self.vradius ** 2) * (self.center[0] - p[0])
            run = (self.hradius ** 2) * (p[1] - self.center[1])
            p2 = Point(simplify(p[0] + run), simplify(p[1] + rise))
            return [Line(p, p2)]
        else:
            if len(self.foci) == 2:
                f1, f2 = self.foci
                maj = self.hradius
                test = 2 * maj - Point.distance(f1, p) - Point.distance(f2, p)
            else:
                test = self.radius - Point.distance(self.center, p)
            if test.is_number and test.is_positive:
                return []
            # else p is outside the ellipse or we can't tell. In case of the
            # latter, the solutions returned will only be valid if
            # the point is not inside the ellipse; if it is, nan will result.
            x, y = Dummy("x"), Dummy("y")
            eq = self.equation(x, y)
            dydx = idiff(eq, y, x)
            slope = Line(p, Point(x, y)).slope
            tangent_points = solve([w.as_numer_denom()[0] for w in [slope - dydx, eq]], [x, y])

            # handle horizontal and vertical tangent lines
            if len(tangent_points) == 1:
                assert tangent_points[0][0] == p[0] or tangent_points[0][1] == p[1]
                return [Line(p, Point(p[0] + 1, p[1])), Line(p, Point(p[0], p[1] + 1))]

            # others
            return [Line(p, tangent_points[0]), Line(p, tangent_points[1])]
示例#3
0
    def tangent_lines(self, p):
        """Tangent lines between `p` and the ellipse.

        If `p` is on the ellipse, returns the tangent line through point `p`.
        Otherwise, returns the tangent line(s) from `p` to the ellipse, or
        None if no tangent line is possible (e.g., `p` inside ellipse).

        Parameters
        ----------
        p : Point

        Returns
        -------
        tangent_lines : list with 1 or 2 Lines

        Raises
        ------
        NotImplementedError
            Can only find tangent lines for a point, `p`, on the ellipse.

        See Also
        --------
        Point
        Line

        Examples
        --------
        >>> from sympy import Point, Ellipse
        >>> e1 = Ellipse(Point(0, 0), 3, 2)
        >>> e1.tangent_lines(Point(3, 0))
        [Line(Point(3, 0), Point(3, -12))]

        >>> # This will plot an ellipse together with a tangent line.
        >>> from sympy import Point, Ellipse, Plot
        >>> e = Ellipse(Point(0,0), 3, 2)
        >>> t = e.tangent_lines(e.random_point()) # doctest: +SKIP
        >>> p = Plot() # doctest: +SKIP
        >>> p[0] = e # doctest: +SKIP
        >>> p[1] = t # doctest: +SKIP

        """
        if self.encloses_point(p):
            return []

        if p in self:
            rise = (self.vradius ** 2)*(self.center[0] - p[0])
            run = (self.hradius ** 2)*(p[1] - self.center[1])
            p2 = Point(simplify(p[0] + run),
                       simplify(p[1] + rise))
            return [Line(p, p2)]
        else:
            if len(self.foci) == 2:
                f1, f2 = self.foci
                maj = self.hradius
                test = (2*maj -
                        Point.distance(f1, p) -
                        Point.distance(f2, p))
            else:
                test = self.radius - Point.distance(self.center, p)
            if test.is_number and test.is_positive:
                return []
            # else p is outside the ellipse or we can't tell. In case of the
            # latter, the solutions returned will only be valid if
            # the point is not inside the ellipse; if it is, nan will result.
            x, y = Dummy('x'), Dummy('y')
            eq = self.equation(x, y)
            dydx = idiff(eq, y, x)
            slope = Line(p, Point(x, y)).slope
            tangent_points = solve([slope - dydx, eq], [x, y])

            # handle horizontal and vertical tangent lines
            if len(tangent_points) == 1:
                assert tangent_points[0][0] == p[0] or tangent_points[0][1] == p[1]
                return [Line(p, Point(p[0]+1, p[1])), Line(p, Point(p[0], p[1]+1))]

            # others
            return [Line(p, tangent_points[0]), Line(p, tangent_points[1])]