Exemple #1
0
    def is_concurrent(*lines):
        """
        Returns True if the set of linear entities are concurrent, False
        otherwise. Two or more linear entities are concurrent if they all
        intersect at a single point.

        Description of Method Used:
        ===========================
            Simply take the first two lines and find their intersection.
            If there is no intersection, then the first two lines were
            parallel and had no intersection so concurrency is impossible
            amongst the whole set. Otherwise, check to see if the
            intersection point of the first two lines is a member on
            the rest of the lines. If so, the lines are concurrent.
        """
        _lines = lines
        lines = GeometryEntity.extract_entities(lines)

        # Concurrency requires intersection at a single point; One linear
        # entity cannot be concurrent.
        if len(lines) <= 1:
            return False

        try:
            # Get the intersection (if parallel)
            p = GeometryEntity.do_intersection(lines[0], lines[1])
            if len(p) == 0: return False

            # Make sure the intersection is on every linear entity
            for line in lines[2:]:
                if p[0] not in line:
                    return False
            return True
        except AttributeError:
            return False
Exemple #2
0
    def bisectors(self):
        """The angle bisectors of the triangle.

        An angle bisector of a triangle is a straight line through a vertex
        which cuts the corresponding angle in half.

        Returns
        -------
        bisectors : dict
            Each key is a vertex (Point) and each value is the corresponding
            bisector (Segment).

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

        Examples
        --------
        >>> from sympy.geometry import Point, Triangle, Segment
        >>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
        >>> t = Triangle(p1, p2, p3)
        >>> from sympy import sqrt
        >>> t.bisectors[p2] == Segment(Point(0, sqrt(2) - 1), Point(1, 0))
        True

        """
        s = self.sides
        v = self.vertices
        c = self.incenter
        l1 = Segment(v[0], GeometryEntity.do_intersection(Line(v[0], c), s[1])[0])
        l2 = Segment(v[1], GeometryEntity.do_intersection(Line(v[1], c), s[2])[0])
        l3 = Segment(v[2], GeometryEntity.do_intersection(Line(v[2], c), s[0])[0])
        return {v[0]: l1, v[1]: l2, v[2]: l3}
Exemple #3
0
    def is_concurrent(*lines):
        """
        Returns True if the set of linear entities are concurrent, False
        otherwise. Two or more linear entities are concurrent if they all
        intersect at a single point.

        Description of Method Used:
        ===========================
            Simply take the first two lines and find their intersection.
            If there is no intersection, then the first two lines were
            parallel and had no intersection so concurrency is impossible
            amongst the whole set. Otherwise, check to see if the
            intersection point of the first two lines is a member on
            the rest of the lines. If so, the lines are concurrent.
        """
        _lines = lines
        lines = GeometryEntity.extract_entities(lines)

        # Concurrency requires intersection at a single point; One linear
        # entity cannot be concurrent.
        if len(lines) <= 1:
            return False

        try:
            # Get the intersection (if parallel)
            p = GeometryEntity.do_intersection(lines[0], lines[1])
            if len(p) == 0: return False

            # Make sure the intersection is on every linear entity
            for line in lines[2:]:
                if p[0] not in line:
                    return False
            return True
        except AttributeError:
            return False
Exemple #4
0
    def bisectors(self):
        """
        The angle bisectors of the triangle in a dictionary where the
        key is the vertex and the value is the bisector at that point.

        Example:
        ========
            >>> from sympy.geometry import Point, Triangle, Segment

            >>> p1,p2,p3 = Point(0,0), Point(1,0), Point(0,1)
            >>> t = Triangle(p1, p2, p3)

            >>> from sympy import sqrt
            >>> t.bisectors[p2] == Segment(Point(0, sqrt(2)-1), Point(1, 0))
            True

        """
        s = self.sides
        v = self.vertices
        c = self.incenter
        l1 = Segment(v[0],
                     GeometryEntity.do_intersection(Line(v[0], c), s[1])[0])
        l2 = Segment(v[1],
                     GeometryEntity.do_intersection(Line(v[1], c), s[2])[0])
        l3 = Segment(v[2],
                     GeometryEntity.do_intersection(Line(v[2], c), s[0])[0])
        return {v[0]: l1, v[1]: l2, v[2]: l3}
Exemple #5
0
def intersection(*entities):
    """The intersection of a collection of GeometryEntity instances.

    Parameters
    ----------
    entities : sequence of GeometryEntity

    Returns
    -------
    intersection : list of GeometryEntity

    Raises
    ------
    NotImplementedError
        When unable to calculate intersection.

    Notes
    -----
    The intersection of any geometrical entity with itself should return
    a list with one item: the entity in question.
    An intersection requires two or more entities. If only a single
    entity is given then the function will return an empty list.
    It is possible for `intersection` to miss intersections that one
    knows exists because the required quantities were not fully
    simplified internally.
    Reals should be converted to Rationals, e.g. Rational(str(real_num))
    or else failures due to floating point issues may result.

    Examples
    --------
    >>> from sympy.geometry import Point, Line, Circle, intersection
    >>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(-1, 5)
    >>> l1, l2 = Line(p1, p2), Line(p3, p2)
    >>> c = Circle(p2, 1)
    >>> intersection(l1, p2)
    [Point(1, 1)]
    >>> intersection(l1, l2)
    [Point(1, 1)]
    >>> intersection(c, p2)
    []
    >>> intersection(c, Point(1, 0))
    [Point(1, 0)]
    >>> intersection(c, l2)
    [Point(1 - 5**(1/2)/5, 1 + 2*5**(1/2)/5), Point(1 + 5**(1/2)/5, 1 - 2*5**(1/2)/5)]

    """
    from entity import GeometryEntity

    entities = GeometryEntity.extract_entities(entities, False)
    if len(entities) <= 1:
        return []

    res = GeometryEntity.do_intersection(entities[0], entities[1])
    for entity in entities[2:]:
        newres = []
        for x in res:
            newres.extend(GeometryEntity.do_intersection(x, entity))
        res = newres
    return res
Exemple #6
0
def intersection(*entities):
    """The intersection of a collection of GeometryEntity instances.

    Parameters
    ----------
    entities : sequence of GeometryEntity

    Returns
    -------
    intersection : list of GeometryEntity

    Raises
    ------
    NotImplementedError
        When unable to calculate intersection.

    Notes
    -----
    The intersection of any geometrical entity with itself should return
    a list with one item: the entity in question.
    An intersection requires two or more entities. If only a single
    entity is given then the function will return an empty list.
    It is possible for `intersection` to miss intersections that one
    knows exists because the required quantities were not fully
    simplified internally.
    Reals should be converted to Rationals, e.g. Rational(str(real_num))
    or else failures due to floating point issues may result.

    Examples
    --------
    >>> from sympy.geometry import Point, Line, Circle, intersection
    >>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(-1, 5)
    >>> l1, l2 = Line(p1, p2), Line(p3, p2)
    >>> c = Circle(p2, 1)
    >>> intersection(l1, p2)
    [Point(1, 1)]
    >>> intersection(l1, l2)
    [Point(1, 1)]
    >>> intersection(c, p2)
    []
    >>> intersection(c, Point(1, 0))
    [Point(1, 0)]
    >>> intersection(c, l2)
    [Point(1 - 5**(1/2)/5, 1 + 2*5**(1/2)/5), Point(1 + 5**(1/2)/5, 1 - 2*5**(1/2)/5)]

    """
    from entity import GeometryEntity

    entities = GeometryEntity.extract_entities(entities, False)
    if len(entities) <= 1:
        return []

    res = GeometryEntity.do_intersection(entities[0], entities[1])
    for entity in entities[2:]:
        newres = []
        for x in res:
            newres.extend(GeometryEntity.do_intersection(x, entity))
        res = newres
    return res
Exemple #7
0
    def is_concurrent(*lines):
        """Is a sequence of linear entities concurrent?

        Two or more linear entities are concurrent if they all
        intersect at a single point.

        Parameters
        ----------
        lines : a sequence of linear entities.

        Returns
        -------
        True if the set of linear entities are concurrent, False
        otherwise.

        Notes
        -----
        Simply take the first two lines and find their intersection.
        If there is no intersection, then the first two lines were
        parallel and had no intersection so concurrency is impossible
        amongst the whole set. Otherwise, check to see if the
        intersection point of the first two lines is a member on
        the rest of the lines. If so, the lines are concurrent.

        Examples
        --------
        >>> from sympy import Point, Line
        >>> p1, p2 = Point(0, 0), Point(3, 5)
        >>> p3, p4 = Point(-2, -2), Point(0, 2)
        >>> l1, l2, l3 = Line(p1, p2), Line(p1, p3), Line(p1, p4)
        >>> l1.is_concurrent(l2, l3)
        True

        >>> l4 = Line(p2, p3)
        >>> l4.is_concurrent(l2, l3)
        False

        """
        _lines = lines
        lines = GeometryEntity.extract_entities(lines)

        # Concurrency requires intersection at a single point; One linear
        # entity cannot be concurrent.
        if len(lines) <= 1:
            return False

        try:
            # Get the intersection (if parallel)
            p = GeometryEntity.do_intersection(lines[0], lines[1])
            if len(p) == 0: return False

            # Make sure the intersection is on every linear entity
            for line in lines[2:]:
                if p[0] not in line:
                    return False
            return True
        except AttributeError:
            return False
Exemple #8
0
    def __new__(cls, *args, **kwargs):
        vertices = GeometryEntity.extract_entities(args, remove_duplicates=False)
        if len(vertices) != 3:
            raise GeometryError("Triangle.__new__ requires three points")

        for p in vertices:
            if not isinstance(p, Point):
                raise GeometryError("Triangle.__new__ requires three points")

        return GeometryEntity.__new__(cls, *vertices, **kwargs)
Exemple #9
0
    def __new__(cls, *args, **kwargs):
        vertices = GeometryEntity.extract_entities(args, remove_duplicates=False)
        if len(vertices) != 3:
            raise GeometryError("Triangle.__new__ requires three points")

        for p in vertices:
            if not isinstance(p, Point):
                raise GeometryError("Triangle.__new__ requires three points")

        return GeometryEntity.__new__(cls, *vertices, **kwargs)
Exemple #10
0
 def intersection(self, o):
     res = []
     for side in self.sides:
         inter = GeometryEntity.do_intersection(side, o)
         if inter is not None:
             res.extend(inter)
     return res
Exemple #11
0
    def is_collinear(*points):
        """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
          =>    v1.y*vi.x - vi.y*v1.x = 0           (*)
        Hence, if we have a vi such that the equality in (*) is False
        then the points are not collinear. We do this test for every
        point in the list, and if all pass then they are collinear.

        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

        """
        points = GeometryEntity.extract_entities(points)
        if len(points) == 0: return False
        if len(points) <= 2: return True # two points always form a line

        # XXX Cross product is used now, but that only extends to three
        #     dimensions. If the concept needs to extend to greater
        #     dimensions then another method would have to be used
        p1 = points[0]
        p2 = points[1]
        v1 = p2 - p1
        for p3 in points[2:]:
            v2 = p3 - p1
            test = simplify(v1[0]*v2[1] - v1[1]*v2[0])
            if simplify(test) != 0:
                return False
        return True
Exemple #12
0
 def __new__(cls, function, limits):
     fun = sympify(function)
     if not ordered_iter(fun) or len(fun) != 2:
         raise ValueError("Function argument should be (x(t), y(t)) but got %s" % str(function))
     if not ordered_iter(limits) or len(limits) != 3:
         raise ValueError("Limit argument should be (t, tmin, tmax) but got %s" % str(limits))
     return GeometryEntity.__new__(cls, tuple(sympify(fun)), tuple(sympify(limits)))
Exemple #13
0
    def __new__(cls, p1, p2, **kwargs):
        if not isinstance(p1, Point) or not isinstance(p2, Point):
            raise TypeError("%s.__new__ requires Point instances" % cls.__name__)
        if p1 == p2:
            raise RuntimeError("%s.__new__ requires two distinct points" % cls.__name__)

        return GeometryEntity.__new__(cls, p1, p2, **kwargs)
Exemple #14
0
    def perpendicular_segment(self, p):
        """Create a perpendicular line segment from `p` to this line.

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

        Returns
        -------
        segment : Segment

        Notes
        -----
        Returns `p` itself if `p` is on this linear entity.

        Examples
        --------
        >>> from sympy import Point, Line
        >>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(0, 2)
        >>> l1 = Line(p1, p2)
        >>> s1 = l1.perpendicular_segment(p3)
        >>> l1.is_perpendicular(s1)
        True
        >>> p3 in s1
        True

        """
        if p in self:
            return p
        pl = self.perpendicular_line(p)
        p2 = GeometryEntity.do_intersection(self, pl)[0]
        return Segment(p, p2)
Exemple #15
0
    def __new__(cls, center=None, hradius=None, vradius=None, eccentricity=None,
                **kwargs):
        hradius = sympify(hradius)
        vradius = sympify(vradius)
        eccentricity = sympify(eccentricity)

        if len(filter(None, (hradius, vradius, eccentricity))) != 2:
            raise ValueError, 'Exactly two arguments between "hradius", '\
                '"vradius", and "eccentricity" must be not None."'

        if eccentricity is not None:
            if hradius is None:
                hradius = vradius / sqrt(1 - eccentricity**2)
            elif vradius is None:
                vradius = hradius * sqrt(1 - eccentricity**2)
        else:
            if hradius is None and vradius is None:
                raise ValueError("At least two arguments between hradius, "
                    "vradius and eccentricity must not be none.")

        if center is None:
            center = Point(0, 0)

        if not isinstance(center, Point):
            raise TypeError("center must be a Point")

        if hradius == vradius:
            return Circle(center, hradius, **kwargs)
        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
Exemple #16
0
 def __new__(cls, function, limits):
     fun = sympify(function)
     if not fun:
         raise GeometryError("%s.__new__ don't know how to handle" % cls.__name__);
     if not isinstance(limits, (list, tuple)) or len(limits) != 3:
         raise ValueError("Limits argument has wrong syntax");
     return GeometryEntity.__new__(cls, fun, limits)
Exemple #17
0
    def __new__(cls, *args, **kwargs):
        if len(args) != 3:
            raise GeometryError("Triangle.__new__ requires three points")

        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
        i = -3
        while i < len(nodup) - 3 and len(nodup) > 2:
            a, b, c = sorted([nodup[i], nodup[i + 1], nodup[i + 2]])
            if Point.is_collinear(a, b, c):
                nodup[i] = a
                nodup[i + 1] = None
                nodup.pop(i + 1)
            i += 1

        vertices = filter(lambda x: x is not None, nodup)

        if len(vertices) == 3:
            return GeometryEntity.__new__(cls, *vertices, **kwargs)
        elif len(vertices) == 2:
            return Segment(*vertices, **kwargs)
        else:
            return Point(*vertices, **kwargs)
Exemple #18
0
    def __new__(cls,
                center=None,
                hradius=None,
                vradius=None,
                eccentricity=None,
                **kwargs):
        hradius = sympify(hradius)
        vradius = sympify(vradius)
        eccentricity = sympify(eccentricity)

        if len(filter(None, (hradius, vradius, eccentricity))) != 2:
            raise ValueError, 'Exactly two arguments between "hradius", '\
                '"vradius", and "eccentricity" must be not None."'

        if eccentricity is not None:
            if hradius is None:
                hradius = vradius / sqrt(1 - eccentricity**2)
            elif vradius is None:
                vradius = hradius * sqrt(1 - eccentricity**2)
        else:
            if hradius is None and vradius is None:
                raise ValueError("At least two arguments between hradius, "
                                 "vradius and eccentricity must not be none.")

        if center is None:
            center = Point(0, 0)

        if not isinstance(center, Point):
            raise TypeError("center must be a Point")

        if hradius == vradius:
            return Circle(center, hradius, **kwargs)
        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
Exemple #19
0
    def __new__(
        cls, center=None, hradius=None, vradius=None, eccentricity=None,
            **kwargs):
        hradius = sympify(hradius)
        vradius = sympify(vradius)

        eccentricity = sympify(eccentricity)

        if center is None:
            center = Point(0, 0)
        else:
            center = Point(center)

        if len(filter(None, (hradius, vradius, eccentricity))) != 2:
            raise ValueError('Exactly two arguments of "hradius", '
                '"vradius", and "eccentricity" must not be None."')

        if eccentricity is not None:
            if hradius is None:
                hradius = vradius / sqrt(1 - eccentricity**2)
            elif vradius is None:
                vradius = hradius * sqrt(1 - eccentricity**2)

        if hradius == vradius:
            return Circle(center, hradius, **kwargs)

        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
Exemple #20
0
    def intersection(self, o):
        """The intersection of two polygons.

        The intersection may be empty and can contain individual Points and
        complete Line Segments.

        Parameters
        ----------
        other: Polygon

        Returns
        -------
        intersection : list
            The list of Segments and Points

        Examples
        --------
        >>> from sympy import Point, Polygon
        >>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
        >>> poly1 = Polygon(p1, p2, p3, p4)
        >>> p5, p6, p7, p8 = map(Point, [(3, 2), (1, -1), (0, 2), (-2, 1)])
        >>> poly2 = Polygon(p5, p6, p7, p8)
        >>> poly1.intersection(poly2)
        [Point(2/3, 0), Point(9/5, 1/5), Point(7/3, 1), Point(1/3, 1)]

        """
        res = []
        for side in self.sides:
            inter = GeometryEntity.do_intersection(side, o)
            if inter is not None:
                res.extend(inter)
        return res
Exemple #21
0
    def __new__(cls, center=None, hradius=None, vradius=None, eccentricity=None,
                **kwargs):
        hradius = sympify(hradius)
        vradius = sympify(vradius)

        eccentricity = sympify(eccentricity)

        if center is None:
            center = Point(0, 0)
        else:
            center = Point(center)

        if len(filter(None, (hradius, vradius, eccentricity))) != 2:
            raise ValueError('Exactly two arguments of "hradius", '\
                '"vradius", and "eccentricity" must not be None."')

        if eccentricity is not None:
            if hradius is None:
                hradius = vradius / sqrt(1 - eccentricity**2)
            elif vradius is None:
                vradius = hradius * sqrt(1 - eccentricity**2)

        if hradius == vradius:
            return Circle(center, hradius, **kwargs)

        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
Exemple #22
0
    def __new__(cls, *args, **kwargs):
        if len(args) != 3:
            raise GeometryError("Triangle.__new__ requires three points")

        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
        i = -3
        while i < len(nodup) - 3 and len(nodup) > 2:
            a, b, c = sorted([nodup[i], nodup[i + 1], nodup[i + 2]])
            if Point.is_collinear(a, b, c):
                nodup[i] = a
                nodup[i + 1] = None
                nodup.pop(i + 1)
            i += 1

        vertices = filter(lambda x: x is not None, nodup)

        if len(vertices) == 3:
            return GeometryEntity.__new__(cls, *vertices, **kwargs)
        elif len(vertices) == 2:
            return Segment(*vertices, **kwargs)
        else:
            return Point(*vertices, **kwargs)
Exemple #23
0
    def __new__(cls, p1, p2, **kwargs):
        if not isinstance(p1, Point) or not isinstance(p2, Point):
            raise TypeError("%s.__new__ requires Point instances" % cls.__name__)
        if p1 == p2:
            raise RuntimeError("%s.__new__ requires two distinct points" % cls.__name__)

        return GeometryEntity.__new__(cls, p1, p2, **kwargs)
Exemple #24
0
    def intersection(self, o):
        """The intersection of two polygons.

        The intersection may be empty and can contain individual Points and
        complete Line Segments.

        Parameters
        ----------
        other: Polygon

        Returns
        -------
        intersection : list
            The list of Segments and Points

        Examples
        --------
        >>> from sympy import Point, Polygon
        >>> p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
        >>> poly1 = Polygon(p1, p2, p3, p4)
        >>> p5, p6, p7, p8 = map(Point, [(3, 2), (1, -1), (0, 2), (-2, 1)])
        >>> poly2 = Polygon(p5, p6, p7, p8)
        >>> poly1.intersection(poly2)
        [Point(2/3, 0), Point(9/5, 1/5), Point(7/3, 1), Point(1/3, 1)]

        """
        res = []
        for side in self.sides:
            inter = GeometryEntity.do_intersection(side, o)
            if inter is not None:
                res.extend(inter)
        return res
Exemple #25
0
    def __new__(cls, p1, p2, **kwargs):
        p1 = Point(p1)
        p2 = Point(p2)
        if p1 == p2:
            # Rolygon returns lower priority classes...should LinearEntity, too?
            return p1  # raise ValueError("%s.__new__ requires two unique Points." % cls.__name__)

        return GeometryEntity.__new__(cls, p1, p2, **kwargs)
Exemple #26
0
    def __new__(cls, p1, p2, **kwargs):
        p1 = Point(p1)
        p2 = Point(p2)
        if p1 == p2:
            # Rolygon returns lower priority classes...should LinearEntity, too?
            return p1  # raise ValueError("%s.__new__ requires two unique Points." % cls.__name__)

        return GeometryEntity.__new__(cls, p1, p2, **kwargs)
Exemple #27
0
def intersection(*entities):
    """
    Finds the intersection between a list GeometryEntity instances. Returns a
    list of all the intersections, Will raise a NotImplementedError exception
    if unable to calculate the intersection.

    Examples:
    =========
        >>> from sympy.geometry import *
        >>> p1,p2,p3 = Point(0,0), Point(1,1), Point(-1, 5)
        >>> l1, l2 = Line(p1, p2), Line(p3, p2)
        >>> c = Circle(p2, 1)
        >>> intersection(l1, p2)
        [Point(1, 1)]
        >>> intersection(l1, l2)
        [Point(1, 1)]
        >>> intersection(c, p2)
        []
        >>> intersection(c, Point(1, 0))
        [Point(1, 0)]
        >>> intersection(c, l2)
        [Point(1 - 5**(1/2)/5, 1 + 2*5**(1/2)/5), Point(1 + 5**(1/2)/5, 1 - 2*5**(1/2)/5)]

    Notes:
    ======
        - The intersection of any geometrical entity with itself should return
          a list with one item: the entity in question.
        - An intersection requires two or more entities. If only a single
          entity is given then one will receive an empty intersection list.
        - It is possible for intersection() to miss intersections that one
          knows exists because the required quantities were not fully
          simplified internally.
    """
    from entity import GeometryEntity

    entities = GeometryEntity.extract_entities(entities, False)
    if len(entities) <= 1: return []

    res = GeometryEntity.do_intersection(entities[0], entities[1])
    for entity in entities[2:]:
        newres = []
        for x in res:
            newres.extend( GeometryEntity.do_intersection(x, entity) )
        res = newres
    return res
Exemple #28
0
def intersection(*entities):
    """
    Finds the intersection between a list GeometryEntity instances. Returns a
    list of all the intersections, Will raise a NotImplementedError exception
    if unable to calculate the intersection.

    Examples:
    =========
        >>> from sympy.geometry import *
        >>> p1,p2,p3 = Point(0,0), Point(1,1), Point(-1, 5)
        >>> l1, l2 = Line(p1, p2), Line(p3, p2)
        >>> c = Circle(p2, 1)
        >>> intersection(l1, p2)
        [Point(1, 1)]
        >>> intersection(l1, l2)
        [Point(1, 1)]
        >>> intersection(c, p2)
        []
        >>> intersection(c, Point(1, 0))
        [Point(1, 0)]
        >>> intersection(c, l2)
        [Point(1 - 1/5*5**(1/2), 1 + 2*5**(1/2)/5), Point(1 + 1/5*5**(1/2), 1 - 2*5**(1/2)/5)]

    Notes:
    ======
        - The intersection of any geometrical entity with itself should return
          a list with one item: the entity in question.
        - An intersection requires two or more entities. If only a single
          entity is given then one will receive an empty intersection list.
        - It is possible for intersection() to miss intersections that one
          knows exists because the required quantities were not fully
          simplified internally.
    """
    from entity import GeometryEntity

    entities = GeometryEntity.extract_entities(entities, False)
    if len(entities) <= 1: return []

    res = GeometryEntity.do_intersection(entities[0], entities[1])
    for entity in entities[2:]:
        newres = []
        for x in res:
            newres.extend( GeometryEntity.do_intersection(x, entity) )
        res = newres
    return res
Exemple #29
0
    def __new__(cls, center, hradius, vradius, **kwargs):
        hradius = sympify(hradius)
        vradius = sympify(vradius)
        if not isinstance(center, Point):
            raise TypeError("center must be be a Point")

        if hradius == vradius:
            return Circle(center, hradius, **kwargs)
        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
Exemple #30
0
    def __new__(cls, center, hradius, vradius, **kwargs):
        hradius = sympify(hradius)
        vradius = sympify(vradius)
        if not isinstance(center, Point):
            raise TypeError("center must be be a Point")

        if hradius == vradius:
            return Circle(center, hradius, **kwargs)
        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
Exemple #31
0
    def __new__(cls, *args, **kwargs):
        if isinstance(args[0], (tuple, list, set)):
            coords = tuple([sympify(x) for x in args[0]])
        else:
            coords = tuple([sympify(x) for x in args])

        if len(coords) != 2:
            raise NotImplementedError("Only two dimensional points currently supported")

        return GeometryEntity.__new__(cls, *coords)
Exemple #32
0
    def __new__(cls, *args, **kwargs):
        if isinstance(args[0], (tuple, list, set)):
            coords = tuple([sympify(x) for x in args[0]])
        else:
            coords = tuple([sympify(x) for x in args])

        if len(coords) != 2:
            raise NotImplementedError("Only two dimensional points currently supported")

        return GeometryEntity.__new__(cls, *coords)
Exemple #33
0
    def __new__(self, c, r, n, **kwargs):
        r = sympify(r)
        if not isinstance(c, Point):
            raise GeometryError("RegularPolygon.__new__ requires c to be a Point instance")
        if not isinstance(r, Basic):
            raise GeometryError("RegularPolygon.__new__ requires r to be a number or Basic instance")
        if n < 3:
            raise GeometryError("RegularPolygon.__new__ requires n >= 3")

        obj = GeometryEntity.__new__(self, c, r, n, **kwargs)
        return obj
Exemple #34
0
    def __new__(self, c, r, n, **kwargs):
        r = sympify(r)
        if not isinstance(c, Point):
            raise GeometryError("RegularPolygon.__new__ requires c to be a Point instance")
        if not isinstance(r, Basic):
            raise GeometryError("RegularPolygon.__new__ requires r to be a number or Basic instance")
        if n < 3:
            raise GeometryError("RegularPolygon.__new__ requires n >= 3")

        obj = GeometryEntity.__new__(self, c, r, n, **kwargs)
        return obj
Exemple #35
0
 def perpendicular_segment(self, p):
     """
     Returns a new Segment which connects p to a point on this linear
     entity and is also perpendicular to this line. Returns p itself
     if p is on this linear entity.
     """
     if p in self:
         return p
     pl = self.perpendicular_line(p)
     p2 = GeometryEntity.do_intersection(self, pl)[0]
     return Segment(p, p2)
Exemple #36
0
 def perpendicular_segment(self, p):
     """
     Returns a new Segment which connects p to a point on this linear
     entity and is also perpendicular to this line. Returns p itself
     if p is on this linear entity.
     """
     if p in self:
         return p
     pl = self.perpendicular_line(p)
     p2 = GeometryEntity.do_intersection(self, pl)[0]
     return Segment(p, p2)
Exemple #37
0
    def is_concyclic(*points):
        """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.

        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
        --------
        >>> from sympy.geometry import Point
        >>> 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

        """
        points = GeometryEntity.extract_entities(points)
        if len(points) == 0: return False
        if len(points) <= 2: return True
        if len(points) == 3: return not Point.is_collinear(*points)

        try:
            from ellipse import Circle
            c = Circle(points[0], points[1], points[2])
            for point in points[3:]:
                if point not in c:
                    return False
            return True
        except GeometryError, e:
            # Circle could not be created, because of collinearity of the
            # three points passed in, hence they are not concyclic.
            return False
Exemple #38
0
    def bisectors(self):
        """
        The angle bisectors of the triangle in a dictionary where the
        key is the vertex and the value is the bisector at that point.

        Example:
        ========
            >>> p1,p2,p3 = Point(0,0), Point(1,0), Point(0,1)
            >>> t = Triangle(p1, p2, p3)

            >>> t.bisectors[p2]
            Segment(Point(0, (-1) + 2**(1/2)), Point(1, 0))
        """
        s = self.sides
        v = self.vertices
        c = self.incenter
        l1 = Segment(v[0], GeometryEntity.do_intersection(Line(v[0], c), s[1])[0])
        l2 = Segment(v[1], GeometryEntity.do_intersection(Line(v[1], c), s[2])[0])
        l3 = Segment(v[2], GeometryEntity.do_intersection(Line(v[2], c), s[0])[0])
        return {v[0]: l1, v[1]: l2, v[2]: l3}
Exemple #39
0
    def __new__(cls, *args, **kwargs):
        if iterable(args[0]):
            coords = Tuple(*args[0])
        elif isinstance(args[0], Point):
            coords = args[0].args
        else:
            coords = Tuple(*args)

        if len(coords) != 2:
            raise NotImplementedError("Only two dimensional points currently supported")

        return GeometryEntity.__new__(cls, *coords)
Exemple #40
0
 def __new__(cls, function, limits):
     fun = sympify(function)
     if not is_sequence(fun) or len(fun) != 2:
         raise ValueError(
             "Function argument should be (x(t), y(t)) but got %s" %
             str(function))
     if not is_sequence(limits) or len(limits) != 3:
         raise ValueError(
             "Limit argument should be (t, tmin, tmax) but got %s" %
             str(limits))
     return GeometryEntity.__new__(cls, tuple(sympify(fun)),
                                   tuple(sympify(limits)))
Exemple #41
0
    def __new__(cls, *args, **kwargs):
        if iterable(args[0]):
            coords = Tuple(*args[0])
        elif isinstance(args[0], Point):
            coords = args[0].args
        else:
            coords = Tuple(*args)

        if len(coords) != 2:
            raise NotImplementedError(
                "Only two dimensional points currently supported")

        return GeometryEntity.__new__(cls, *coords)
Exemple #42
0
    def __new__(self, c, r, n, rot=0, **kwargs):
        r, n, rot = sympify([r, n, rot])
        c = Point(c)
        if not isinstance(r, Basic):
            raise GeometryError("RegularPolygon.__new__ requires r to be a number or Basic instance")
        if n < 3:
            raise GeometryError("RegularPolygon.__new__ requires n >= 3")

        obj = GeometryEntity.__new__(self, c, r, n, **kwargs)
        obj._n = n
        obj._center = c
        obj._radius = r
        obj._rot = rot
        return obj
Exemple #43
0
    def __new__(cls, *args, **kwargs):
        if iterable(args[0]):
            coords = Tuple(*args[0])
        elif isinstance(args[0], Point):
            coords = args[0].args
        else:
            coords = Tuple(*args)

        if len(coords) != 2:
            raise NotImplementedError("Only two dimensional points currently supported")
        if kwargs.get('evaluate', True):
            coords = [nsimplify(c) for c in coords]

        return GeometryEntity.__new__(cls, *coords)
Exemple #44
0
    def bisectors(self):
        """The angle bisectors of the triangle.

        An angle bisector of a triangle is a straight line through a vertex
        which cuts the corresponding angle in half.

        Returns
        -------
        bisectors : dict
            Each key is a vertex (Point) and each value is the corresponding
            bisector (Segment).

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

        Examples
        --------
        >>> from sympy.geometry import Point, Triangle, Segment
        >>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
        >>> t = Triangle(p1, p2, p3)
        >>> from sympy import sqrt
        >>> t.bisectors[p2] == Segment(Point(0, sqrt(2) - 1), Point(1, 0))
        True

        """
        s = self.sides
        v = self.vertices
        c = self.incenter
        l1 = Segment(v[0],
                     GeometryEntity.do_intersection(Line(v[0], c), s[1])[0])
        l2 = Segment(v[1],
                     GeometryEntity.do_intersection(Line(v[1], c), s[2])[0])
        l3 = Segment(v[2],
                     GeometryEntity.do_intersection(Line(v[2], c), s[0])[0])
        return {v[0]: l1, v[1]: l2, v[2]: l3}
Exemple #45
0
    def rotate(self, angle, pt=None):
        """Override GeometryEntity.rotate to first rotate the RegularPolygon
        about its center.

        >>> from sympy import Point, RegularPolygon, Polygon, pi
        >>> t = RegularPolygon(Point(1, 0), 1, 3)
        >>> t[0] # vertex on x-axis
        Point(2, 0)
        >>> t.rotate(pi/2).vertices[0] # vertex on y axis now
        Point(0, 2)
        """

        r = type(self)(*self.args) # need a copy or else changes are in-place
        r._rot += angle
        return GeometryEntity.rotate(r, angle, pt)
Exemple #46
0
    def rotate(self, angle, pt=None):
        """Override GeometryEntity.rotate to first rotate the RegularPolygon
        about its center.

        >>> from sympy import Point, RegularPolygon, Polygon, pi
        >>> t = RegularPolygon(Point(1, 0), 1, 3)
        >>> t[0] # vertex on x-axis
        Point(2, 0)
        >>> t.rotate(pi/2).vertices[0] # vertex on y axis now
        Point(0, 2)
        """

        r = type(self)(*self.args)  # need a copy or else changes are in-place
        r._rot += angle
        return GeometryEntity.rotate(r, angle, pt)
Exemple #47
0
    def __new__(cls, *args, **kwargs):
        if iterable(args[0]):
            coords = Tuple(*args[0])
        elif isinstance(args[0], Point):
            coords = args[0].args
        else:
            coords = Tuple(*args)

        if len(coords) != 2:
            raise NotImplementedError(
                "Only two dimensional points currently supported")
        if kwargs.get('evaluate', True):
            coords = [simplify(nsimplify(c, rational=True)) for c in coords]

        return GeometryEntity.__new__(cls, *coords)
Exemple #48
0
    def bisectors(self):
        """
        The angle bisectors of the triangle in a dictionary where the
        key is the vertex and the value is the bisector at that point.

        Example:
        ========
            >>> from sympy.geometry import Point, Triangle, Segment

            >>> p1,p2,p3 = Point(0,0), Point(1,0), Point(0,1)
            >>> t = Triangle(p1, p2, p3)

            >>> from sympy import sqrt
            >>> t.bisectors[p2] == Segment(Point(0, sqrt(2)-1), Point(1, 0))
            True

        """
        s = self.sides
        v = self.vertices
        c = self.incenter
        l1 = Segment(v[0], GeometryEntity.do_intersection(Line(v[0], c), s[1])[0])
        l2 = Segment(v[1], GeometryEntity.do_intersection(Line(v[1], c), s[2])[0])
        l3 = Segment(v[2], GeometryEntity.do_intersection(Line(v[2], c), s[0])[0])
        return {v[0]: l1, v[1]: l2, v[2]: l3}
Exemple #49
0
    def __new__(self, c, r, n, rot=0, **kwargs):
        r, n, rot = sympify([r, n, rot])
        c = Point(c)
        if not isinstance(r, Basic):
            raise GeometryError(
                "RegularPolygon.__new__ requires r to be a number or Basic instance"
            )
        if n < 3:
            raise GeometryError("RegularPolygon.__new__ requires n >= 3")

        obj = GeometryEntity.__new__(self, c, r, n, **kwargs)
        obj._n = n
        obj._center = c
        obj._radius = r
        obj._rot = rot
        return obj
Exemple #50
0
    def __new__(cls, *args, **kwargs):
        c, r = None, None
        if len(args) == 3 and isinstance(args[0], Point):
            from polygon import Triangle
            t = Triangle(args[0], args[1], args[2])
            if t.area == 0:
                raise GeometryError("Cannot construct a circle from three collinear points")
            c = t.circumcenter
            r = t.circumradius
        elif len(args) == 2:
            # Assume (center, radius) pair
            c = args[0]
            r = sympify(args[1])

        if not (c is None or r is None):
            return GeometryEntity.__new__(cls, c, r, **kwargs)

        raise GeometryError("Circle.__new__ received unknown arguments")
Exemple #51
0
    def __new__(cls, *args, **kwargs):
        c, r = None, None
        if len(args) == 3 and isinstance(args[0], Point):
            from polygon import Triangle
            t = Triangle(args[0], args[1], args[2])
            if t.area == 0:
                raise GeometryError("Cannot construct a circle from three collinear points")
            c = t.circumcenter
            r = t.circumradius
        elif len(args) == 2:
            # Assume (center, radius) pair
            c = args[0]
            r = sympify(args[1])

        if not (c is None or r is None):
            return GeometryEntity.__new__(cls, c, r, **kwargs)

        raise GeometryError("Circle.__new__ received unknown arguments")
Exemple #52
0
    def is_concyclic(*points):
        """
        Test whether or not a set of points are concyclic (i.e., on the same
        circle). Returns True if they are concyclic, or False otherwise.

        Example:
        ========
            >>> from sympy.geometry import Point
            >>> 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

        Description of method used:
        ===========================
            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, we pick the first three points and
            attempt to create a circle. 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 all of the other points for containment in the circle.
        """
        points = GeometryEntity.extract_entities(points)
        if len(points) == 0: return False
        if len(points) <= 2: return True
        if len(points) == 3: return (not Point.is_collinear(*points))

        try:
            from ellipse import Circle
            c = Circle(points[0], points[1], points[2])
            for point in points[3:]:
                if point not in c:
                    return False
            return True
        except GeometryError, e:
            # Circle could not be created, because of collinearity of the
            # three points passed in, hence they are not concyclic.
            return False
Exemple #53
0
    def projection(self, o):
        """
        Project a point, line, ray, or segment onto this linear entity.
        If projection cannot be performed then a GeometryError is raised.

        Notes:
        ======
            - A projection involves taking the two points that define
              the linear entity and projecting those points onto a
              Line and then reforming the linear entity using these
              projections.
            - A point P is projected onto a line L by finding the point
              on L that is closest to P. This is done by creating a
              perpendicular line through P and L and finding its
              intersection with L.
        """
        tline = Line(self.p1, self.p2)

        def project(p):
            """Project a point onto the line representing self."""
            if p in tline: return p
            l1 = tline.perpendicular_line(p)
            return tline.intersection(l1)[0]

        projected = None
        if isinstance(o, Point):
            return project(o)
        elif isinstance(o, LinearEntity):
            n_p1 = project(o.p1)
            n_p2 = project(o.p2)
            if n_p1 == n_p2:
                projected = n_p1
            else:
                projected = o.__class__(n_p1, n_p2)

        # Didn't know how to project so raise an error
        if projected is None:
            n1 = self.__class__.__name__
            n2 = o.__class__.__name__
            raise GeometryError("Do not know how to project %s onto %s" %
                                (n2, n1))

        return GeometryEntity.do_intersection(self, projected)[0]
Exemple #54
0
    def is_concyclic(*points):
        """
        Test whether or not a set of points are concyclic (i.e., on the same
        circle). Returns True if they are concyclic, or False otherwise.

        Example:
        ========
            >>> from sympy.geometry import Point
            >>> 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

        Description of method used:
        ===========================
            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, we pick the first three points and
            attempt to create a circle. 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 all of the other points for containment in the circle.
        """
        points = GeometryEntity.extract_entities(points)
        if len(points) == 0: return False
        if len(points) <= 2: return True
        if len(points) == 3: return (not Point.is_collinear(*points))

        try:
            from ellipse import Circle
            c = Circle(points[0], points[1], points[2])
            for point in points[3:]:
                if point not in c:
                    return False
            return True
        except GeometryError,e:
            # Circle could not be created, because of collinearity of the
            # three points passed in, hence they are not concyclic.
            return False
Exemple #55
0
    def __new__(cls, *args, **kwargs):
        c, r = None, None
        if len(args) == 3:
            args = [Point(a) for a in args]
            if Point.is_collinear(*args):
                raise GeometryError("Cannot construct a circle from three collinear points")
            from polygon import Triangle
            t = Triangle(*args)
            c = t.circumcenter
            r = t.circumradius
        elif len(args) == 2:
            # Assume (center, radius) pair
            c = Point(args[0])
            r = sympify(args[1])

        if not (c is None or r is None):
            return GeometryEntity.__new__(cls, c, r, **kwargs)

        raise GeometryError("Circle.__new__ received unknown arguments")
Exemple #56
0
    def orthocenter(self):
        """The orthocenter of the triangle.

        The orthocenter is the intersection of the altitudes of a triangle.

        Returns
        -------
        orthocenter : Point

        See Also
        --------
        Point

        Examples
        --------
        >>> from sympy.geometry import Point, Triangle
        >>> p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
        >>> t = Triangle(p1, p2, p3)

        """
        a = self.altitudes
        return GeometryEntity.intersect(a[1], a[2])[0]