<commit_before>from sympy.core import Basic, S, C, sympify, oo, pi, Symbol
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.elementary.trigonometric import cos, sin
from sympy.simplify import simplify
from sympy.geometry.exceptions import GeometryError
from sympy.solvers import solve
from entity import GeometryEntity
from point import Point
from ellipse import Circle
from line import Line, Segment, Ray

import warnings

class Polygon(GeometryEntity):
    """A two-dimensional polygon.

    A simple polygon in space. Can be constructed from a sequence of points
    or from a center, radius, number of sides and rotation angle.

    Parameters
    ----------
    vertices : sequence of Points

    Attributes
    ----------
    area
    angles
    perimeter
    vertices
    centroid
    sides

    Raises
    ------
    GeometryError
        If all parameters are not Points.

        If the Polygon has intersecting sides.

    See Also
    --------
    Point
    Segment
    Triangle

    Notes
    -----
    Polygons are treated as closed paths rather than 2D areas so
    some calculations can be be negative or positive (e.g., area)
    based on the orientation of the points.

    Any consecutive identical points are reduced to a single point
    and any points collinear and between two points will be removed
    unless they are needed to define an explicit intersection (see examples).

    A Triangle, Segment or Point will be returned when there are 3 or
    fewer points provided.

    Examples
    --------
    >>> from sympy import Point, Polygon
    >>> p1, p2, p3, p4, p5 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1), (3, 0)])
    >>> Polygon(p1, p2, p3, p4)
    Polygon(Point(0, 0), Point(1, 0), Point(5, 1), Point(0, 1))
    >>> Polygon(p1, p2)
    Segment(Point(0, 0), Point(1, 0))
    >>> Polygon(p1, p2, p5)
    Segment(Point(0, 0), Point(3, 0))

    While not sides of a polygon are allowed to cross implicitly, they
    can do so explicitly. So a polygon shaped like a Z must have the
    point in the middle of the Z explicitly given:

    >>> mid = Point(1, 1)
    >>> Polygon(Point(0,2),Point(2,2), mid, Point(0,0),Point(2,0), mid).area
    0

    """

    def __new__(cls, *args, **kwargs):
        if kwargs.get('n', 0):
            n = kwargs.pop('n')
            args = list(args)
            # return a virtual polygon with n sides
            if len(args) == 2: # center, radius
                args.append(n)
            elif len(args) == 3: # center, radius, rotation
                args.insert(2, n)
            return RegularPolygon(*args, **kwargs)

        vertices = [Point(a) for a in args]

        # remove consecutive duplicates
        nodup = []
        for p in vertices:
            if nodup and p == nodup[-1]:
                continue
            nodup.append(p)
        if len(nodup) > 1 and nodup[-1] == nodup[0]:
            nodup.pop() # last point was same as first

        # remove collinear points unless they are shared points<commit_msg>edit Polygon docstring re self-crossing and n<commit_after>from sympy.core import Basic, S, C, sympify, oo, pi, Symbol
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.elementary.trigonometric import cos, sin
from sympy.simplify import simplify
from sympy.geometry.exceptions import GeometryError
from sympy.solvers import solve
from entity import GeometryEntity
from point import Point
from ellipse import Circle
from line import Line, Segment, Ray

import warnings

class Polygon(GeometryEntity):
    """A two-dimensional polygon.

    A simple polygon in space. Can be constructed from a sequence of points
    or from a center, radius, number of sides and rotation angle.

    Parameters
    ----------
    vertices : sequence of Points

    Attributes
    ----------
    area
    angles
    perimeter
    vertices
    centroid
    sides

    Raises
    ------
    GeometryError
        If all parameters are not Points.

        If the Polygon has intersecting sides.

    See Also
    --------
    Point
    Segment
    Triangle

    Notes
    -----
    Polygons are treated as closed paths rather than 2D areas so
    some calculations can be be negative or positive (e.g., area)
    based on the orientation of the points.

    Any consecutive identical points are reduced to a single point
    and any points collinear and between two points will be removed
    unless they are needed to define an explicit intersection (see examples).

    A Triangle, Segment or Point will be returned when there are 3 or
    fewer points provided.

    Examples
    --------
    >>> from sympy import Point, Polygon, pi
    >>> p1, p2, p3, p4, p5 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1), (3, 0)])
    >>> Polygon(p1, p2, p3, p4)
    Polygon(Point(0, 0), Point(1, 0), Point(5, 1), Point(0, 1))
    >>> Polygon(p1, p2)
    Segment(Point(0, 0), Point(1, 0))
    >>> Polygon(p1, p2, p5)
    Segment(Point(0, 0), Point(3, 0))

    While the sides of a polygon are not allowed to cross implicitly, they
    can do so explicitly. For example, a polygon shaped like a Z with the top
    left connecting to the bottom right of the Z must have the point in the
    middle of the Z explicitly given:

    >>> mid = Point(1, 1)
    >>> Polygon((0, 2), (2, 2), mid, (0, 0), (2, 0), mid).area
    0
    >>> Polygon((0, 2), (2, 2), mid, (2, 0), (0, 0), mid).area
    -2

    When the the keyword `n` is used to define the number of sides of the
    Polygon then a RegularPolygon is created and the other arguments are
    interpreted as center, radius and rotation. The unrotated RegularPolygon
    will always have a vertex at Point(r, 0) where `r` is the radius of the
    circle that circumscribes the RegularPolygon.

    >>> p = Polygon((0,0), 1, n=3)
    >>> p
    RegularPolygon(Point(0, 0), 1, 3, 0)
    >>> p[0]
    Point(1, 0)
    >>> p.vertices[0]
    Point(1, 0)
    >>> p.args[0]
    Point(0, 0)
    >>> p.rotate(pi/2)
    >>> p[0]
    Point(0, 1)

    """

    def __new__(cls, *args, **kwargs):
        if kwargs.get('n', 0):
            n = kwargs.pop('n')
            args = list(args)
            # return a virtual polygon with n sides
            if len(args) == 2: # center, radius
                args.append(n)
            elif len(args) == 3: # center, radius, rotation
                args.insert(2, n)
            return RegularPolygon(*args, **kwargs)

        vertices = [Point(a) for a in args]

        # remove consecutive duplicates
        nodup = []
        for p in vertices:
            if nodup and p == nodup[-1]:
                continue
            nodup.append(p)
        if len(nodup) > 1 and nodup[-1] == nodup[0]:
            nodup.pop() # last point was same as first

        # remove collinear points unless they are shared points
{'fraction_non_alphanumeric': 0.10619598652409551, 'fraction_numerical': 0.022557492309945804, 'mean_word_length': 2.342143906020558, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5185337', 'n_tokens_mistral': 2131, 'n_tokens_neox': 1996, 'n_words': 825}