B
    [                 @   s8  d Z ddlmZmZ ddlZddlmZmZmZ ddl	m
Z
 ddlmZmZmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddl	mZ ddlm Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(Z(m)Z)m*Z* ddl+m,Z, G dd de,Z-G dd de-Z.G dd de-Z/dS )aS  Geometrical Points.

Contains
========
Point
Point2D
Point3D

When methods of Point require 1 or more points as arguments, they
can be passed as a sequence of coordinates or Points:

>>> from sympy.geometry.point import Point
>>> Point(1, 1).is_collinear((2, 2), (3, 4))
False
>>> Point(1, 1).is_collinear(Point(2, 2), Point(3, 4))
False

    )divisionprint_functionN)SsympifyExpr)Number)iterableis_sequenceas_int)Tuple)	nsimplifysimplify)GeometryError)sqrt)im)Matrix)Eq)Float)global_evaluate)Add)	FiniteSet)uniq)
filldedent	func_nameUndecidable   )GeometryEntityc               @   sb  e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zedd Zedd  Zed!d" Zed#d$ Zd%d& Zd'd( Zd)d* ZdJd,d-Zd.d/ Zd0d1 Zd2d3 Zed4d5 Z d6d7 Z!ed8d9 Z"ed:d; Z#d<d= Z$ed>d? Z%ed@dA Z&edBdC Z'dDdE Z(dFdG Z)edHdI Z*eZ+e	Z,d+S )KPointa  A point in a n-dimensional Euclidean space.

    Parameters
    ==========

    coords : sequence of n-coordinate values. In the special
        case where n=2 or 3, a Point2D or Point3D will be created
        as appropriate.
    evaluate : if `True` (default), all floats are turn into
        exact types.
    dim : number of coordinates the point should have.  If coordinates
        are unspecified, they are padded with zeros.
    on_morph : indicates what should happen when the number of
        coordinates of a point need to be changed by adding or
        removing zeros.  Possible values are `'warn'`, `'error'`, or
        `ignore` (default).  No warning or error is given when `*args`
        is empty and `dim` is given. An error is always raised when
        trying to remove nonzero coordinates.


    Attributes
    ==========

    length
    origin: A `Point` representing the origin of the
        appropriately-dimensioned space.

    Raises
    ======

    TypeError : When instantiating with anything but a Point or sequence
    ValueError : when instantiating with a sequence with length < 2 or
        when trying to reduce dimensions if keyword `on_morph='error'` is
        set.

    See Also
    ========

    sympy.geometry.line.Segment : Connects two Points

    Examples
    ========

    >>> from sympy.geometry import Point
    >>> from sympy.abc import x
    >>> Point(1, 2, 3)
    Point3D(1, 2, 3)
    >>> Point([1, 2])
    Point2D(1, 2)
    >>> Point(0, x)
    Point2D(0, x)
    >>> Point(dim=4)
    Point(0, 0, 0, 0)

    Floats are automatically converted to Rational unless the
    evaluate flag is False:

    >>> Point(0.5, 0.25)
    Point2D(1/2, 1/4)
    >>> Point(0.5, 0.25, evaluate=False)
    Point2D(0.5, 0.25)

    Tc             O   s(  | dtd }| dd}t|dkr0|d n|}t|tr^d}t|| dt|kr^|S t|s|ttdt	|t|dkr| dd rt
jf| d }t| }| dt|}t|d	k rttd
t||kr8d|t||}|dkrn6|dkrt|n"|dkr,t| nttdtdd ||d  D r\tdtdd |D rxtdtdd |D std|d | t
jf|t|   }|r|tdd |tD }t|d	krd|d< t||S t|dkrd|d< t||S tj| f| S )Nevaluater   on_morphignorer   Fdimz<
                Expecting sequence of coordinates, not `{}`   z[
                Point requires 2 or more coordinates or
                keyword `dim` > 1.z1Dimension of {} needs to be changedfrom {} to {}.errorwarnzf
                        on_morph value should be 'error',
                        'warn' or 'ignore'.c             s   s   | ]
}|V  qd S )N ).0ir%   r%   3lib/python3.7/site-packages/sympy/geometry/point.py	<genexpr>   s    z Point.__new__.<locals>.<genexpr>z&Nonzero coordinates cannot be removed.c             s   s   | ]}|j ot|V  qd S )N)Z	is_numberr   )r&   ar%   r%   r(   r)      s    z(Imaginary coordinates are not permitted.c             s   s   | ]}t |tV  qd S )N)
isinstancer   )r&   r*   r%   r%   r(   r)      s    z,Coordinates must be valid SymPy expressions.c             S   s    g | ]}|t t|d dfqS )T)Zrational)r   r   )r&   fr%   r%   r(   
<listcomp>   s   z!Point.__new__.<locals>.<listcomp>T_nocheck   )getr   lenr+   r   r	   	TypeErrorr   formatr   r   Zeror   
ValueErrorwarningsr$   anyallZxreplacedictZatomsr   Point2DPoint3Dr   __new__)clsargskwargsr   r   coordsr!   messager%   r%   r(   r<   o   s^    




 

zPoint.__new__c             C   s   t dgt|  }t || S )z7Returns the distance between this point and the origin.r   )r   r1   distance)selforiginr%   r%   r(   __abs__   s    zPoint.__abs__c             C   s`   yt | t |dd\}}W n" tk
r>   td|Y nX dd t||D }t |ddS )aG  Add other to self by incrementing self's coordinates by
        those of other.

        Notes
        =====

        >>> from sympy.geometry.point import Point

        When sequences of coordinates are passed to Point methods, they
        are converted to a Point internally. This __add__ method does
        not do that so if floating point values are used, a floating
        point result (in terms of SymPy Floats) will be returned.

        >>> Point(1, 2) + (.1, .2)
        Point2D(1.1, 2.2)

        If this is not desired, the `translate` method can be used or
        another Point can be added:

        >>> Point(1, 2).translate(.1, .2)
        Point2D(11/10, 11/5)
        >>> Point(1, 2) + Point(.1, .2)
        Point2D(11/10, 11/5)

        See Also
        ========

        sympy.geometry.point.Point.translate

        F)r   z+Don't know how to add {} and a Point objectc             S   s   g | ]\}}t || qS r%   )r   )r&   r*   br%   r%   r(   r-      s    z!Point.__add__.<locals>.<listcomp>)r   _normalize_dimensionr2   r   r3   zip)rC   othersor@   r%   r%   r(   __add__   s    zPoint.__add__c             C   s
   || j kS )N)r>   )rC   itemr%   r%   r(   __contains__   s    zPoint.__contains__c                s(   t    fdd| jD }t|ddS )z'Divide point's coordinates by a factor.c                s   g | ]}t |  qS r%   )r   )r&   x)divisorr%   r(   r-      s    z!Point.__div__.<locals>.<listcomp>F)r   )r   r>   r   )rC   rP   r@   r%   )rP   r(   __div__   s    zPoint.__div__c             C   s.   t |trt| jt|jkr"dS | j|jkS )NF)r+   r   r1   r>   )rC   rI   r%   r%   r(   __eq__   s    zPoint.__eq__c             C   s
   | j | S )N)r>   )rC   keyr%   r%   r(   __getitem__   s    zPoint.__getitem__c             C   s
   t | jS )N)hashr>   )rC   r%   r%   r(   __hash__   s    zPoint.__hash__c             C   s
   | j  S )N)r>   __iter__)rC   r%   r%   r(   rW      s    zPoint.__iter__c             C   s
   t | jS )N)r1   r>   )rC   r%   r%   r(   __len__   s    zPoint.__len__c                s(   t    fdd| jD }t|ddS )a{  Multiply point's coordinates by a factor.

        Notes
        =====

        >>> from sympy.geometry.point import Point

        When multiplying a Point by a floating point number,
        the coordinates of the Point will be changed to Floats:

        >>> Point(1, 2)*0.1
        Point2D(0.1, 0.2)

        If this is not desired, the `scale` method can be used or
        else only multiply or divide by integers:

        >>> Point(1, 2).scale(1.1, 1.1)
        Point2D(11/10, 11/5)
        >>> Point(1, 2)*11/10
        Point2D(11/10, 11/5)

        See Also
        ========

        sympy.geometry.point.Point.scale
        c                s   g | ]}t |  qS r%   )r   )r&   rO   )factorr%   r(   r-     s    z!Point.__mul__.<locals>.<listcomp>F)r   )r   r>   r   )rC   rY   r@   r%   )rY   r(   __mul__   s    zPoint.__mul__c             C   s   dd | j D }t|ddS )zNegate the point.c             S   s   g | ]
}| qS r%   r%   )r&   rO   r%   r%   r(   r-     s    z!Point.__neg__.<locals>.<listcomp>F)r   )r>   r   )rC   r@   r%   r%   r(   __neg__  s    zPoint.__neg__c             C   s   | dd |D  S )zPSubtract two points, or subtract a factor from this point's
        coordinates.c             S   s   g | ]
}| qS r%   r%   )r&   rO   r%   r%   r(   r-   $  s    z!Point.__sub__.<locals>.<listcomp>r%   )rC   rI   r%   r%   r(   __sub__!  s    zPoint.__sub__c                sz   t | dd d   dkr2tdd |D  t fdd|D rPt|S  d< ddd< fd	d
|D S )z~Ensure that points have the same dimension.
        By default `on_morph='warn'` is passed to the
        `Point` constructor._ambient_dimensionNr!   c             s   s   | ]}|j V  qd S )N)ambient_dimension)r&   r'   r%   r%   r(   r)   1  s    z-Point._normalize_dimension.<locals>.<genexpr>c             3   s   | ]}|j  kV  qd S )N)r^   )r&   r'   )r!   r%   r(   r)   2  s    r   r$   c                s   g | ]}t |f qS r%   )r   )r&   r'   )r?   r%   r(   r-   6  s    z.Point._normalize_dimension.<locals>.<listcomp>)getattrr0   maxr8   list)r=   pointsr?   r%   )r!   r?   r(   rG   &  s    zPoint._normalize_dimensionc                 s`   t | dkrdS tjdd | D  }|d   fdd|dd D }tdd |D }| S )	ag  The affine rank of a set of points is the dimension
        of the smallest affine space containing all the points.
        For example, if the points lie on a line (and are not all
        the same) their affine rank is 1.  If the points lie on a plane
        but not a line, their affine rank is 2.  By convention, the empty
        set has affine rank -1.r   c             S   s   g | ]}t |qS r%   )r   )r&   r'   r%   r%   r(   r-   E  s    z%Point.affine_rank.<locals>.<listcomp>c                s   g | ]}|  qS r%   r%   )r&   r'   )rD   r%   r(   r-   G  s    r   Nc             S   s   g | ]
}|j qS r%   )r>   )r&   r'   r%   r%   r(   r-   I  s    )r1   r   rG   r   rank)r>   rb   mr%   )rD   r(   affine_rank8  s    	zPoint.affine_rankc             C   s   t | dt| S )z$Number of components this point has.r]   )r_   r1   )rC   r%   r%   r(   r^   L  s    zPoint.ambient_dimensionc             G   sP   t |dkrdS | jdd |D  }|d jdkr6dS tt|}tj| dkS )a  Return True if there exists a plane in which all the points
        lie.  A trivial True value is returned if `len(points) < 3` or
        all Points are 2-dimensional.

        Parameters
        ==========

        A set of points

        Raises
        ======

        ValueError : if less than 3 unique points are given

        Returns
        =======

        boolean

        Examples
        ========

        >>> from sympy import Point3D
        >>> p1 = Point3D(1, 2, 2)
        >>> p2 = Point3D(2, 7, 2)
        >>> p3 = Point3D(0, 0, 2)
        >>> p4 = Point3D(1, 1, 2)
        >>> Point3D.are_coplanar(p1, p2, p3, p4)
        True
        >>> p5 = Point3D(0, 1, 3)
        >>> Point3D.are_coplanar(p1, p2, p3, p5)
        False

        r   Tc             S   s   g | ]}t |qS r%   )r   )r&   r'   r%   r%   r(   r-   x  s    z&Point.are_coplanar.<locals>.<listcomp>r   r"   )r1   rG   r^   ra   r   r   rf   )r=   rb   r%   r%   r(   are_coplanarQ  s    $zPoint.are_coplanarc             C   s0   t | t |\}}ttdd t||D  S )ap  The Euclidean distance from self to point p.

        Parameters
        ==========

        p : Point

        Returns
        =======

        distance : number or symbolic expression.

        See Also
        ========

        sympy.geometry.line.Segment.length
        sympy.geometry.point.Point.taxicab_distance

        Examples
        ========

        >>> from sympy.geometry import Point
        >>> p1, p2 = Point(1, 1), Point(4, 5)
        >>> p1.distance(p2)
        5

        >>> from sympy.abc import x, y
        >>> p3 = Point(x, y)
        >>> p3.distance(Point(0, 0))
        sqrt(x**2 + y**2)

        c             s   s   | ]\}}|| d  V  qdS )r"   Nr%   )r&   r*   rF   r%   r%   r(   r)     s    z!Point.distance.<locals>.<genexpr>)r   rG   r   r   rH   )rC   prJ   r%   r%   r(   rB     s    !zPoint.distancec             C   s(   t |st|}tdd t| |D  S )z.Return dot product of self with another Point.c             s   s   | ]\}}|| V  qd S )Nr%   )r&   r*   rF   r%   r%   r(   r)     s    zPoint.dot.<locals>.<genexpr>)r	   r   r   rH   )rC   rh   r%   r%   r(   dot  s    z	Point.dotc             C   s6   t |trt| t|krdS tdd t| |D S )z8Returns whether the coordinates of self and other agree.Fc             s   s   | ]\}}| |V  qd S )N)equals)r&   r*   rF   r%   r%   r(   r)     s    zPoint.equals.<locals>.<genexpr>)r+   r   r1   r8   rH   )rC   rI   r%   r%   r(   rj     s    zPoint.equalsNc                s$    fdd| j D }t|ddiS )aF  Evaluate the coordinates of the point.

        This method will, where possible, create and return a new Point
        where the coordinates are evaluated as floating point numbers to
        the precision indicated (default=15).

        Parameters
        ==========

        prec : int

        Returns
        =======

        point : Point

        Examples
        ========

        >>> from sympy import Point, Rational
        >>> p1 = Point(Rational(1, 2), Rational(3, 2))
        >>> p1
        Point2D(1/2, 3/2)
        >>> p1.evalf()
        Point2D(0.5, 1.5)

        c                s   g | ]}|j f qS r%   )evalf)r&   rO   )optionsprecr%   r(   r-     s    zPoint.evalf.<locals>.<listcomp>r   F)r>   r   )rC   rm   rl   r@   r%   )rl   rm   r(   rk     s    zPoint.evalfc             C   s^   t |tst|}t |trT| |kr*| gS t| |\}}|| krP||krP| gS g S || S )aX  The intersection between this point and another GeometryEntity.

        Parameters
        ==========

        other : Point

        Returns
        =======

        intersection : list of Points

        Notes
        =====

        The return value will either be an empty list if there is no
        intersection, otherwise it will contain this point.

        Examples
        ========

        >>> from sympy import Point
        >>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(0, 0)
        >>> p1.intersection(p2)
        []
        >>> p1.intersection(p3)
        [Point2D(0, 0)]

        )r+   r   r   rG   intersection)rC   rI   Zp1Zp2r%   r%   r(   rn     s    

zPoint.intersectionc             G   s8   | f| }t jdd |D  }tt|}t j| dkS )a  Returns `True` if there exists a line
        that contains `self` and `points`.  Returns `False` otherwise.
        A trivially True value is returned if no points are given.

        Parameters
        ==========

        args : sequence of Points

        Returns
        =======

        is_collinear : boolean

        See Also
        ========

        sympy.geometry.line.Line

        Examples
        ========

        >>> from sympy import Point
        >>> from sympy.abc import x
        >>> p1, p2 = Point(0, 0), Point(1, 1)
        >>> p3, p4, p5 = Point(2, 2), Point(x, x), Point(1, 2)
        >>> Point.is_collinear(p1, p2, p3, p4)
        True
        >>> Point.is_collinear(p1, p2, p3, p5)
        False

        c             S   s   g | ]}t |qS r%   )r   )r&   r'   r%   r%   r(   r-     s    z&Point.is_collinear.<locals>.<listcomp>r   )r   rG   ra   r   rf   )rC   r>   rb   r%   r%   r(   is_collinear  s    !
zPoint.is_collinearc                s   | f| }t jdd |D  }tt|}t j| dks<dS |d   fdd|D }tdd |D }| \}}t |krdS dS )	a  Do `self` and the given sequence of points lie in a circle?

        Returns True if the set of points are concyclic and
        False otherwise. A trivial value of True is returned
        if there are fewer than 2 other points.

        Parameters
        ==========

        args : sequence of Points

        Returns
        =======

        is_concyclic : boolean


        Examples
        ========

        >>> from sympy import Point

        Define 4 points that are on the unit circle:

        >>> p1, p2, p3, p4 = Point(1, 0), (0, 1), (-1, 0), (0, -1)

        >>> p1.is_concyclic() == p1.is_concyclic(p2, p3, p4) == True
        True

        Define a point not on that circle:

        >>> p = Point(1, 1)

        >>> p.is_concyclic(p1, p2, p3)
        False

        c             S   s   g | ]}t |qS r%   )r   )r&   r'   r%   r%   r(   r-   E  s    z&Point.is_concyclic.<locals>.<listcomp>r"   Fr   c                s   g | ]}|  qS r%   r%   )r&   rh   )rD   r%   r(   r-   J  s    c             S   s    g | ]}t |||g qS r%   )ra   ri   )r&   r'   r%   r%   r(   r-   P  s    T)r   rG   ra   r   rf   r   rrefr1   )rC   r>   rb   Zmatrp   Zpivotsr%   )rD   r(   is_concyclic  s    &
zPoint.is_concyclicc             C   s   | j }|dkrdS | S )zrTrue if any coordinate is nonzero, False if every coordinate is zero,
        and None if it cannot be determined.N)is_zero)rC   rr   r%   r%   r(   
is_nonzeroV  s    zPoint.is_nonzeroc       
      C   s   t | t |\}}|jdkrf|j|j \}}\}}|| ||  d}|dkrfttd||f t|j|jg}	|	 dk S )z{Returns whether each coordinate of `self` is a scalar
        multiple of the corresponding coordinate in point p.
        r"   r   NzDcan't determine if %s is a scalar multiple of
                    %s)	r   rG   r^   r>   rj   r   r   r   rd   )
rC   rh   rJ   rK   Zx1Zy1Zx2Zy2rvre   r%   r%   r(   is_scalar_multiple_  s    
zPoint.is_scalar_multiplec             C   s6   dd | j D }t|rdS tdd |D r2dS dS )zsTrue if every coordinate is zero, False if any coordinate is not zero,
        and None if it cannot be determined.c             S   s   g | ]
}|j qS r%   )rs   )r&   rO   r%   r%   r(   r-   v  s    z!Point.is_zero.<locals>.<listcomp>Fc             s   s   | ]}|d kV  qd S )Nr%   )r&   rO   r%   r%   r(   r)   y  s    z Point.is_zero.<locals>.<genexpr>NT)r>   r7   )rC   Znonzeror%   r%   r(   rr   r  s    zPoint.is_zeroc             C   s   t jS )z
        Treating a Point as a Line, this returns 0 for the length of a Point.

        Examples
        ========

        >>> from sympy import Point
        >>> p = Point(0, 1)
        >>> p.length
        0
        )r   r4   )rC   r%   r%   r(   length}  s    zPoint.lengthc             C   s,   t | t |\}}t dd t||D S )a  The midpoint between self and point p.

        Parameters
        ==========

        p : Point

        Returns
        =======

        midpoint : Point

        See Also
        ========

        sympy.geometry.line.Segment.midpoint

        Examples
        ========

        >>> from sympy.geometry import Point
        >>> p1, p2 = Point(1, 1), Point(13, 5)
        >>> p1.midpoint(p2)
        Point2D(7, 3)

        c             S   s"   g | ]\}}t || tj qS r%   )r   r   ZHalf)r&   r*   rF   r%   r%   r(   r-     s    z"Point.midpoint.<locals>.<listcomp>)r   rG   rH   )rC   rh   rJ   r%   r%   r(   midpoint  s    zPoint.midpointc             C   s   t dgt|  ddS )zOA point of all zeros of the same ambient dimension
        as the current pointr   F)r   )r   r1   )rC   r%   r%   r(   rD     s    zPoint.originc             C   sx   | j }| d tjkr,tdg|d dg  S | d tjkrTtddg|d dg  S t| d  | d g|d dg  S )a~  Returns a non-zero point that is orthogonal to the
        line containing `self` and the origin.

        Examples
        ========

        >>> from sympy.geometry import Line, Point
        >>> a = Point(1, 2, 3)
        >>> a.orthogonal_direction
        Point3D(-2, 1, 0)
        >>> b = _
        >>> Line(b, b.origin).is_perpendicular(Line(a, a.origin))
        True
        r   r   r"   )r^   r   r4   r   )rC   r!   r%   r%   r(   orthogonal_direction  s    zPoint.orthogonal_directionc             C   s>   t t | t |\} }|jr&td|| |||  S )a  Project the point `a` onto the line between the origin
        and point `b` along the normal direction.

        Parameters
        ==========

        a : Point
        b : Point

        Returns
        =======

        p : Point

        See Also
        ========

        sympy.geometry.line.LinearEntity.projection

        Examples
        ========

        >>> from sympy.geometry import Line, Point
        >>> a = Point(1, 2)
        >>> b = Point(2, 5)
        >>> z = a.origin
        >>> p = Point.project(a, b)
        >>> Line(p, a).is_perpendicular(Line(p, b))
        True
        >>> Point.is_collinear(z, p, b)
        True
        z"Cannot project to the zero vector.)r   rG   rr   r5   ri   )r*   rF   r%   r%   r(   project  s    "zPoint.projectc             C   s,   t | t |\}}tdd t||D  S )a;  The Taxicab Distance from self to point p.

        Returns the sum of the horizontal and vertical distances to point p.

        Parameters
        ==========

        p : Point

        Returns
        =======

        taxicab_distance : The sum of the horizontal
        and vertical distances to point p.

        See Also
        ========

        sympy.geometry.point.Point.distance

        Examples
        ========

        >>> from sympy.geometry import Point
        >>> p1, p2 = Point(1, 1), Point(4, 5)
        >>> p1.taxicab_distance(p2)
        7

        c             s   s   | ]\}}t || V  qd S )N)abs)r&   r*   rF   r%   r%   r(   r)     s    z)Point.taxicab_distance.<locals>.<genexpr>)r   rG   r   rH   )rC   rh   rJ   r%   r%   r(   taxicab_distance  s    zPoint.taxicab_distancec             C   s@   t | t |\}}| jr(|jr(tdtdd t||D  S )a  The Canberra Distance from self to point p.

        Returns the weighted sum of horizontal and vertical distances to
        point p.

        Parameters
        ==========

        p : Point

        Returns
        =======

        canberra_distance : The weighted sum of horizontal and vertical
        distances to point p. The weight used is the sum of absolute values
        of the coordinates.

        See Also
        ========

        sympy.geometry.point.Point.distance

        Examples
        ========

        >>> from sympy.geometry import Point
        >>> p1, p2 = Point(1, 1), Point(3, 3)
        >>> p1.canberra_distance(p2)
        1
        >>> p1, p2 = Point(0, 0), Point(3, 3)
        >>> p1.canberra_distance(p2)
        2

        Raises
        ======

        ValueError when both vectors are zero.

        See Also
        ========

        sympy.geometry.point.Point.distance

        z"Cannot project to the zero vector.c             s   s.   | ]&\}}t || t |t |  V  qd S )N)rz   )r&   r*   rF   r%   r%   r(   r)   C  s    z*Point.canberra_distance.<locals>.<genexpr>)r   rG   rr   r5   r   rH   )rC   rh   rJ   r%   r%   r(   canberra_distance  s    .zPoint.canberra_distancec             C   s   | t |  S )zdReturn the Point that is in the same direction as `self`
        and a distance of 1 from the origin)rz   )rC   r%   r%   r(   unitE  s    z
Point.unit)N)-__name__
__module____qualname____doc__Zis_Pointr<   rE   rL   rN   rQ   rR   rT   rV   rW   rX   rZ   r[   r\   classmethodrG   staticmethodrf   propertyr^   rg   rB   ri   rj   rk   rn   ro   rq   rs   ru   rr   rv   rw   rD   rx   ry   r{   r|   r}   n__truediv__r%   r%   r%   r(   r   ,   sN   ?H'.$
)&8	'!3r   c               @   sn   e Zd ZdZdZdd Zdd Zedd Zdd
dZ	dddZ
dd ZdddZedd Zedd Zd	S )r:   a  A point in a 2-dimensional Euclidean space.

    Parameters
    ==========

    coords : sequence of 2 coordinate values.

    Attributes
    ==========

    x
    y
    length

    Raises
    ======

    TypeError
        When trying to add or subtract points with different dimensions.
        When trying to create a point with more than two dimensions.
        When `intersection` is called with object other than a Point.

    See Also
    ========

    sympy.geometry.line.Segment : Connects two Points

    Examples
    ========

    >>> from sympy.geometry import Point2D
    >>> from sympy.abc import x
    >>> Point2D(1, 2)
    Point2D(1, 2)
    >>> Point2D([1, 2])
    Point2D(1, 2)
    >>> Point2D(0, x)
    Point2D(0, x)

    Floats are automatically converted to Rational unless the
    evaluate flag is False:

    >>> Point2D(0.5, 0.25)
    Point2D(1/2, 1/4)
    >>> Point2D(0.5, 0.25, evaluate=False)
    Point2D(0.5, 0.25)

    r"   c             O   s.   | ddsd|d< t||}tj| f| S )Nr.   Fr"   r!   )popr   r   r<   )r=   r>   r?   r%   r%   r(   r<     s    
zPoint2D.__new__c             C   s   || kS )Nr%   )rC   rM   r%   r%   r(   rN     s    zPoint2D.__contains__c             C   s   | j | j| j | jfS )zwReturn a tuple (xmin, ymin, xmax, ymax) representing the bounding
        rectangle for the geometric figure.

        )rO   y)rC   r%   r%   r(   bounds  s    zPoint2D.boundsNc             C   s   ddl m}m}m} ||}||}| }|dk	rD||dd}||8 }|j\}	}
|||	 ||
  ||	 ||
  }|dk	r||7 }|S )aX  Rotate ``angle`` radians counterclockwise about Point ``pt``.

        See Also
        ========

        rotate, scale

        Examples
        ========

        >>> from sympy import Point2D, pi
        >>> t = Point2D(1, 0)
        >>> t.rotate(pi/2)
        Point2D(0, 1)
        >>> t.rotate(pi/2, (2, 0))
        Point2D(2, -1)

        r   )cossinr   Nr"   )r!   )Zsympyr   r   r   r>   )rC   Zangleptr   r   r   crJ   rt   rO   r   r%   r%   r(   rotate  s    
"zPoint2D.rotater   c             C   sD   |r.t |dd}| j| j ||j|j S t | j| | j| S )a  Scale the coordinates of the Point by multiplying by
        ``x`` and ``y`` after subtracting ``pt`` -- default is (0, 0) --
        and then adding ``pt`` back again (i.e. ``pt`` is the point of
        reference for the scaling).

        See Also
        ========

        rotate, translate

        Examples
        ========

        >>> from sympy import Point2D
        >>> t = Point2D(1, 1)
        >>> t.scale(2)
        Point2D(2, 1)
        >>> t.scale(2, 2)
        Point2D(2, 2)

        r"   )r!   )r   	translater>   scalerO   r   )rC   rO   r   r   r%   r%   r(   r     s    zPoint2D.scalec             C   sv   y|j \}}|jo|dk}W n tk
r4   d}Y nX |sBtd| j\}}ttdd||dg|  d dd  S )zReturn the point after applying the transformation described
        by the 3x3 Matrix, ``matrix``.

        See Also
        ========
        geometry.entity.rotate
        geometry.entity.scale
        geometry.entity.translate
        r/   Fz;The argument to the transform function must be a 3x3 matrixr   r   Nr"   )shape	is_squareAttributeErrorr5   r>   r   r   tolist)rC   matrixcolrowvalid_matrixrO   r   r%   r%   r(   	transform  s    



zPoint2D.transformr   c             C   s   t | j| | j| S )a  Shift the Point by adding x and y to the coordinates of the Point.

        See Also
        ========

        rotate, scale

        Examples
        ========

        >>> from sympy import Point2D
        >>> t = Point2D(0, 1)
        >>> t.translate(2)
        Point2D(2, 1)
        >>> t.translate(2, 2)
        Point2D(2, 3)
        >>> t + Point2D(2, 2)
        Point2D(2, 3)

        )r   rO   r   )rC   rO   r   r%   r%   r(   r     s    zPoint2D.translatec             C   s
   | j d S )z
        Returns the X coordinate of the Point.

        Examples
        ========

        >>> from sympy import Point2D
        >>> p = Point2D(0, 1)
        >>> p.x
        0
        r   )r>   )rC   r%   r%   r(   rO     s    z	Point2D.xc             C   s
   | j d S )z
        Returns the Y coordinate of the Point.

        Examples
        ========

        >>> from sympy import Point2D
        >>> p = Point2D(0, 1)
        >>> p.y
        1
        r   )r>   )rC   r%   r%   r(   r     s    z	Point2D.y)N)r   r   N)r   r   )r~   r   r   r   r]   r<   rN   r   r   r   r   r   r   rO   r   r%   r%   r%   r(   r:   O  s   0	
"

r:   c               @   s   e Zd ZdZdZdd Zdd Zedd Zd	d
 Z	dd Z
dd ZdddZdd ZdddZedd Zedd Zedd ZdS ) r;   a6  A point in a 3-dimensional Euclidean space.

    Parameters
    ==========

    coords : sequence of 3 coordinate values.

    Attributes
    ==========

    x
    y
    z
    length

    Raises
    ======

    TypeError
        When trying to add or subtract points with different dimensions.
        When `intersection` is called with object other than a Point.

    Examples
    ========

    >>> from sympy import Point3D
    >>> from sympy.abc import x
    >>> Point3D(1, 2, 3)
    Point3D(1, 2, 3)
    >>> Point3D([1, 2, 3])
    Point3D(1, 2, 3)
    >>> Point3D(0, x, 3)
    Point3D(0, x, 3)

    Floats are automatically converted to Rational unless the
    evaluate flag is False:

    >>> Point3D(0.5, 0.25, 2)
    Point3D(1/2, 1/4, 2)
    >>> Point3D(0.5, 0.25, 3, evaluate=False)
    Point3D(0.5, 0.25, 3)

    r/   c             O   s.   | ddsd|d< t||}tj| f| S )Nr.   Fr/   r!   )r   r   r   r<   )r=   r>   r?   r%   r%   r(   r<   L  s    
zPoint3D.__new__c             C   s   || kS )Nr%   )rC   rM   r%   r%   r(   rN   R  s    zPoint3D.__contains__c              G   s
   t j|  S )a  Is a sequence of points collinear?

        Test whether or not a set of points are collinear. Returns True if
        the set of points are collinear, or False otherwise.

        Parameters
        ==========

        points : sequence of Point

        Returns
        =======

        are_collinear : boolean

        See Also
        ========

        sympy.geometry.line.Line3D

        Examples
        ========

        >>> from sympy import Point3D, Matrix
        >>> from sympy.abc import x
        >>> p1, p2 = Point3D(0, 0, 0), Point3D(1, 1, 1)
        >>> p3, p4, p5 = Point3D(2, 2, 2), Point3D(x, x, x), Point3D(1, 2, 6)
        >>> Point3D.are_collinear(p1, p2, p3, p4)
        True
        >>> Point3D.are_collinear(p1, p2, p3, p5)
        False
        )r   ro   )rb   r%   r%   r(   are_collinearU  s    "zPoint3D.are_collinearc             C   sN   |  |}ttdd |D  }|j| j | |j| j | |j| j | gS )ap  
        Gives the direction cosine between 2 points

        Parameters
        ==========

        p : Point3D

        Returns
        =======

        list

        Examples
        ========

        >>> from sympy import Point3D
        >>> p1 = Point3D(1, 2, 3)
        >>> p1.direction_cosine(Point3D(2, 3, 5))
        [sqrt(6)/6, sqrt(6)/6, sqrt(6)/3]
        c             s   s   | ]}|d  V  qdS )r"   Nr%   )r&   r'   r%   r%   r(   r)     s    z+Point3D.direction_cosine.<locals>.<genexpr>)direction_ratior   r   rO   r   z)rC   pointr*   rF   r%   r%   r(   direction_cosiney  s    
zPoint3D.direction_cosinec             C   s"   |j | j  |j| j |j| j gS )aV  
        Gives the direction ratio between 2 points

        Parameters
        ==========

        p : Point3D

        Returns
        =======

        list

        Examples
        ========

        >>> from sympy import Point3D
        >>> p1 = Point3D(1, 2, 3)
        >>> p1.direction_ratio(Point3D(2, 3, 5))
        [1, 1, 2]
        )rO   r   r   )rC   r   r%   r%   r(   r     s    zPoint3D.direction_ratioc             C   s<   t |tst|dd}t |tr2| |kr.| gS g S || S )ac  The intersection between this point and another point.

        Parameters
        ==========

        other : Point

        Returns
        =======

        intersection : list of Points

        Notes
        =====

        The return value will either be an empty list if there is no
        intersection, otherwise it will contain this point.

        Examples
        ========

        >>> from sympy import Point3D
        >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(0, 0, 0)
        >>> p1.intersection(p2)
        []
        >>> p1.intersection(p3)
        [Point3D(0, 0, 0)]

        r/   )r!   )r+   r   r   r;   rn   )rC   rI   r%   r%   r(   rn     s    

zPoint3D.intersectionr   Nc             C   sJ   |r,t |}| j| j |||j|j S t | j| | j| | j| S )a  Scale the coordinates of the Point by multiplying by
        ``x`` and ``y`` after subtracting ``pt`` -- default is (0, 0) --
        and then adding ``pt`` back again (i.e. ``pt`` is the point of
        reference for the scaling).

        See Also
        ========

        translate

        Examples
        ========

        >>> from sympy import Point3D
        >>> t = Point3D(1, 1, 1)
        >>> t.scale(2)
        Point3D(2, 1, 1)
        >>> t.scale(2, 2)
        Point3D(2, 2, 1)

        )r;   r   r>   r   rO   r   r   )rC   rO   r   r   r   r%   r%   r(   r     s     zPoint3D.scalec       
      C   s   y|j \}}|jo|dk}W n tk
r4   d}Y nX |sBtdddlm} | j\}}}||}	ttdd|||dg|	 	 d dd  S )	zReturn the point after applying the transformation described
        by the 4x4 Matrix, ``matrix``.

        See Also
        ========
        geometry.entity.rotate
        geometry.entity.scale
        geometry.entity.translate
           Fz;The argument to the transform function must be a 4x4 matrixr   )	Transposer   Nr/   )
r   r   r   r5   Zsympy.matrices.expressionsr   r>   r;   r   r   )
rC   r   r   r   r   r   rO   r   r   re   r%   r%   r(   r     s    


zPoint3D.transformr   c             C   s   t | j| | j| | j| S )a  Shift the Point by adding x and y to the coordinates of the Point.

        See Also
        ========

        rotate, scale

        Examples
        ========

        >>> from sympy import Point3D
        >>> t = Point3D(0, 1, 1)
        >>> t.translate(2)
        Point3D(2, 1, 1)
        >>> t.translate(2, 2)
        Point3D(2, 3, 1)
        >>> t + Point3D(2, 2, 2)
        Point3D(2, 3, 3)

        )r;   rO   r   r   )rC   rO   r   r   r%   r%   r(   r     s    zPoint3D.translatec             C   s
   | j d S )z
        Returns the X coordinate of the Point.

        Examples
        ========

        >>> from sympy import Point3D
        >>> p = Point3D(0, 1, 3)
        >>> p.x
        0
        r   )r>   )rC   r%   r%   r(   rO     s    z	Point3D.xc             C   s
   | j d S )z
        Returns the Y coordinate of the Point.

        Examples
        ========

        >>> from sympy import Point3D
        >>> p = Point3D(0, 1, 2)
        >>> p.y
        1
        r   )r>   )rC   r%   r%   r(   r   +  s    z	Point3D.yc             C   s
   | j d S )z
        Returns the Z coordinate of the Point.

        Examples
        ========

        >>> from sympy import Point3D
        >>> p = Point3D(0, 1, 1)
        >>> p.z
        1
        r"   )r>   )rC   r%   r%   r(   r   :  s    z	Point3D.z)r   r   r   N)r   r   r   )r~   r   r   r   r]   r<   rN   r   r   r   r   rn   r   r   r   r   rO   r   r   r%   r%   r%   r(   r;     s   +$&

r;   )0r   Z
__future__r   r   r6   Z
sympy.corer   r   r   Zsympy.core.numbersr   Zsympy.core.compatibilityr   r	   r
   Zsympy.core.containersr   Zsympy.simplifyr   r   Zsympy.geometry.exceptionsr   Z(sympy.functions.elementary.miscellaneousr   Z$sympy.functions.elementary.complexesr   Zsympy.matricesr   Zsympy.core.relationalr   r   Zsympy.core.evaluater   Zsympy.core.addr   Z
sympy.setsr   Zsympy.utilities.iterablesr   Zsympy.utilities.miscr   r   r   Zentityr   r   r:   r;   r%   r%   r%   r(   <module>   s:         ) O