<commit_before>"""Geometrical Points.

Contains
========
Point
"""

from ..core import Add, Float, Integer, Tuple
from ..core.compatibility import iterable
from ..core.evaluate import global_evaluate
from ..core.sympify import sympify
from ..functions import im, sqrt
from ..matrices import Matrix
from ..simplify import nsimplify, simplify
from ..utilities import ordered
from .entity import GeometryEntity


class Point(GeometryEntity):
    """A point in a n-dimensional Euclidean space.

    Parameters
    ==========

    coords : sequence of n-coordinate values.

    Raises
    ======

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

    See Also
    ========

    diofant.geometry.line.Segment : Connects two Points

    Examples
    ========

    >>> Point([1, 2])
    Point(1, 2)
    >>> Point(0, x)
    Point(0, x)

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

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

    """

    def __new__(cls, *args, **kwargs):
        evaluate = kwargs.get('evaluate', global_evaluate[0])

        if iterable(args[0]):
            args = args[0]

        # unpack the arguments into a friendly Tuple
        # if we were already a Point, we're doing an excess
        # iteration, but we'll worry about efficiency later
        coords = Tuple(*args)
        if any(a.is_number and im(a) for a in coords):
            raise ValueError('Imaginary coordinates not permitted.')

        # Turn any Floats into rationals and simplify
        # any expressions before we instantiate
        if evaluate:
            coords = coords.xreplace({f: simplify(nsimplify(f, rational=True))
                                      for f in coords.atoms(Float)})
        if len(coords) != 2:
            raise ValueError('Only two dimensional points currently supported')

        return GeometryEntity.__new__(cls, *coords)

    def __contains__(self, item):
        return item == self

    def is_concyclic(*points):  # pylint: disable=no-method-argument
        """Is a sequence of points concyclic?

        Test whether or not a sequence of points are concyclic (i.e., they lie
        on a circle).

        Parameters
        ==========

        points : sequence of Points

        Returns
        =======

        is_concyclic : boolean
            True if points are concyclic, False otherwise.

        See Also
        ========

        diofant.geometry.ellipse.Circle

        Notes
        =====

        No points are not considered to be concyclic. One or two points
        are definitely concyclic and three points are conyclic iff they
        are not collinear.

        For more than three points, create a circle from the first three
        points. If the circle cannot be created (i.e., they are collinear)
        then all of the points cannot be concyclic. If the circle is created
        successfully then simply check the remaining points for containment
        in the circle.

        Examples
        ========

        >>> p1, p2 = Point(-1, 0), Point(1, 0)
        >>> p3, p4 = Point(0, 1), Point(-1, 2)
        >>> Point.is_concyclic(p1, p2, p3)
        True
        >>> Point.is_concyclic(p1, p2, p3, p4)
        False

        """
        if not all(isinstance(p, Point) for p in points):
            raise TypeError('Must pass only Point objects')

        if len(points) == 0:
            return False
        if len(points) <= 2:
            return True

        ppoints = list(ordered(Point(p) for p in points))

        from .ellipse import Circle
        try:
            c = Circle(ppoints[0], ppoints[1], ppoints[2])
        except ValueError:
            return False
        for point in ppoints[3:]:
            if point not in c:
                return False
        return True

    def is_collinear(*args):  # pylint: disable=no-method-argument
        """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
        =======

        is_collinear : boolean

        Notes
        =====

        Slope is preserved everywhere on a line, so the slope between
        any two points on the line should be the same. Take the first
        two points, p1 and p2, and create a translated point v1
        with p1 as the origin. Now for every other point we create
        a translated point, vi with p1 also as the origin. Note that
        these translations preserve slope since everything is
        consistently translated to a new origin of p1. Since slope
        is preserved then we have the following equality:

              * v1_slope = vi_slope
              * v1.y/v1.x = vi.y/vi.x (due to translation)
              * v1.y*vi.x = vi.y*v1.x<commit_msg>Disable few errors for new pylint<commit_after>"""Geometrical Points.

Contains
========
Point
"""

from ..core import Add, Float, Integer, Tuple
from ..core.compatibility import iterable
from ..core.evaluate import global_evaluate
from ..core.sympify import sympify
from ..functions import im, sqrt
from ..matrices import Matrix
from ..simplify import nsimplify, simplify
from ..utilities import ordered
from .entity import GeometryEntity


class Point(GeometryEntity):
    """A point in a n-dimensional Euclidean space.

    Parameters
    ==========

    coords : sequence of n-coordinate values.

    Raises
    ======

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

    See Also
    ========

    diofant.geometry.line.Segment : Connects two Points

    Examples
    ========

    >>> Point([1, 2])
    Point(1, 2)
    >>> Point(0, x)
    Point(0, x)

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

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

    """

    def __new__(cls, *args, **kwargs):
        evaluate = kwargs.get('evaluate', global_evaluate[0])

        if iterable(args[0]):
            args = args[0]

        # unpack the arguments into a friendly Tuple
        # if we were already a Point, we're doing an excess
        # iteration, but we'll worry about efficiency later
        coords = Tuple(*args)
        if any(a.is_number and im(a) for a in coords):
            raise ValueError('Imaginary coordinates not permitted.')

        # Turn any Floats into rationals and simplify
        # any expressions before we instantiate
        if evaluate:
            coords = coords.xreplace({f: simplify(nsimplify(f, rational=True))
                                      for f in coords.atoms(Float)})
        if len(coords) != 2:
            raise ValueError('Only two dimensional points currently supported')

        return GeometryEntity.__new__(cls, *coords)

    def __contains__(self, item):
        return item == self

    def is_concyclic(*points):  # pylint: disable=no-method-argument,no-self-argument
        """Is a sequence of points concyclic?

        Test whether or not a sequence of points are concyclic (i.e., they lie
        on a circle).

        Parameters
        ==========

        points : sequence of Points

        Returns
        =======

        is_concyclic : boolean
            True if points are concyclic, False otherwise.

        See Also
        ========

        diofant.geometry.ellipse.Circle

        Notes
        =====

        No points are not considered to be concyclic. One or two points
        are definitely concyclic and three points are conyclic iff they
        are not collinear.

        For more than three points, create a circle from the first three
        points. If the circle cannot be created (i.e., they are collinear)
        then all of the points cannot be concyclic. If the circle is created
        successfully then simply check the remaining points for containment
        in the circle.

        Examples
        ========

        >>> p1, p2 = Point(-1, 0), Point(1, 0)
        >>> p3, p4 = Point(0, 1), Point(-1, 2)
        >>> Point.is_concyclic(p1, p2, p3)
        True
        >>> Point.is_concyclic(p1, p2, p3, p4)
        False

        """
        if not all(isinstance(p, Point) for p in points):
            raise TypeError('Must pass only Point objects')

        if len(points) == 0:
            return False
        if len(points) <= 2:
            return True

        ppoints = list(ordered(Point(p) for p in points))

        from .ellipse import Circle
        try:
            c = Circle(ppoints[0], ppoints[1], ppoints[2])
        except ValueError:
            return False
        for point in ppoints[3:]:
            if point not in c:
                return False
        return True

    def is_collinear(*args):  # pylint: disable=no-method-argument,no-self-argument
        """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
        =======

        is_collinear : boolean

        Notes
        =====

        Slope is preserved everywhere on a line, so the slope between
        any two points on the line should be the same. Take the first
        two points, p1 and p2, and create a translated point v1
        with p1 as the origin. Now for every other point we create
        a translated point, vi with p1 also as the origin. Note that
        these translations preserve slope since everything is
        consistently translated to a new origin of p1. Since slope
        is preserved then we have the following equality:

              * v1_slope = vi_slope
              * v1.y/v1.x = vi.y/vi.x (due to translation)
              * v1.y*vi.x = vi.y*v1.x
{'fraction_non_alphanumeric': 0.0928361138370952, 'fraction_numerical': 0.012757605495583905, 'mean_word_length': 2.0732810615199035, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4706707', 'n_tokens_mistral': 2930, 'n_tokens_neox': 2682, 'n_words': 1086}