コード例 #1
0
ファイル: polygon.py プロジェクト: unix0000/sympy-polys
    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)
コード例 #2
0
ファイル: ellipse.py プロジェクト: solus9/sympy
    def __new__(cls, *args, **kwargs):
        from sympy.geometry.util import find
        from .polygon import Triangle
        evaluate = kwargs.get('evaluate', global_parameters.evaluate)
        if len(args) == 1 and isinstance(args[0], (Expr, Eq)):
            x = kwargs.get('x', 'x')
            y = kwargs.get('y', 'y')
            equation = args[0]
            if isinstance(equation, Eq):
                equation = equation.lhs - equation.rhs
            x = find(x, equation)
            y = find(y, equation)

            try:
                a, b, c, d, e = linear_coeffs(equation, x**2, y**2, x, y)
            except ValueError:
                raise GeometryError(
                    "The given equation is not that of a circle.")

            if a == 0 or b == 0 or a != b:
                raise GeometryError(
                    "The given equation is not that of a circle.")

            center_x = -c / a / 2
            center_y = -d / b / 2
            r2 = (center_x**2) + (center_y**2) - e

            return Circle((center_x, center_y), sqrt(r2), evaluate=evaluate)

        else:
            c, r = None, None
            if len(args) == 3:
                args = [Point(a, dim=2, evaluate=evaluate) for a in args]
                t = Triangle(*args)
                if not isinstance(t, Triangle):
                    return t
                c = t.circumcenter
                r = t.circumradius
            elif len(args) == 2:
                # Assume (center, radius) pair
                c = Point(args[0], dim=2, evaluate=evaluate)
                r = args[1]
                # this will prohibit imaginary radius
                try:
                    r = Point(r, 0, evaluate=evaluate).x
                except ValueError:
                    raise GeometryError(
                        "Circle with imaginary radius is not permitted")

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

            raise GeometryError("Circle.__new__ received unknown arguments")
コード例 #3
0
ファイル: polygon.py プロジェクト: unix0000/sympy-polys
    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
コード例 #4
0
    def __new__(cls, *args, **kwargs):
        from sympy.geometry.util import find
        from .polygon import Triangle

        if len(args) == 1 and isinstance(args[0], Expr):
            x = kwargs.get('x', 'x')
            y = kwargs.get('y', 'y')
            equation = args[0]
            if isinstance(equation, Eq):
                equation = equation.lhs - equation.rhs
            x = find(x, equation)
            y = find(y, equation)

            try:
                co = linear_coeffs(equation, x**2, y**2, x, y)
            except ValueError:
                raise GeometryError(
                    "The given equation is not that of a circle.")

            a, b, c, d, e = [co[i] for i in (x**2, y**2, x, y, 0)]

            if a == 0 or b == 0 or a != b:
                raise GeometryError(
                    "The given equation is not that of a circle.")

            center_x = -c / a / 2
            center_y = -d / b / 2
            r2 = (center_x**2) + (center_y**2) - e

            return Circle((center_x, center_y), sqrt(r2))

        else:
            c, r = None, None
            if len(args) == 3:
                args = [Point(a, dim=2) for a in args]
                t = Triangle(*args)
                if not isinstance(t, Triangle):
                    return t
                c = t.circumcenter
                r = t.circumradius
            elif len(args) == 2:
                # Assume (center, radius) pair
                c = Point(args[0], dim=2)
                r = sympify(args[1])

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

            raise GeometryError("Circle.__new__ received unknown arguments")
コード例 #5
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
コード例 #6
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)
コード例 #7
0
ファイル: curve.py プロジェクト: jcockayne/sympy-rkern
 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)
コード例 #8
0
ファイル: plane.py プロジェクト: akshayah3/sympy
    def random_point(self, seed=None):
        """ Returns a random point on the Plane.

        Returns
        =======

        Point3D

        """
        x, y, z = symbols("x, y, z")
        a = self.equation(x, y, z)
        from sympy import Rational
        import random
        if seed is not None:
            rng = random.Random(seed)
        else:
            rng = random
        for i in range(10):
            c = 2 * Rational(rng.random()) - 1
            s = sqrt(1 - c**2)
            a = solve(a.subs([(y, c), (z, s)]))
            if a is []:
                d = Point3D(0, c, s)
            else:
                d = Point3D(a[0], c, s)
            if d in self:
                return d
        raise GeometryError('Having problems generating a point in the plane')
コード例 #9
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")
コード例 #10
0
ファイル: ellipse.py プロジェクト: tomtwohats/sympy
    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")
コード例 #11
0
ファイル: ellipse.py プロジェクト: nerdishhomosapein/sympy
    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, dim=2)

        if len(center) != 2:
            raise ValueError('The center of "{}" must be a two dimensional point'.format(cls))

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

        if eccentricity is not None:
            if eccentricity.is_negative:
                raise GeometryError("Eccentricity of ellipse/circle should lie between [0, 1)")
            elif 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)

        if hradius == 0 or vradius == 0:
            return Segment(Point(center[0] - hradius, center[1] - vradius), Point(center[0] + hradius, center[1] + vradius))

        if hradius.is_real is False or vradius.is_real is False:
            raise GeometryError("Invalid value encountered when computing hradius / vradius.")

        return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
コード例 #12
0
ファイル: line.py プロジェクト: yuri-karadzhov/sympy
    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]
コード例 #13
0
ファイル: point.py プロジェクト: woshiwushupei/sympy
    def __add__(self, other):
        """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

        """
        try:
            s, o = Point._normalize_dimension(self, Point(other,
                                                          evaluate=False))
        except TypeError:
            raise GeometryError(
                "Don't know how to add {} and a Point object".format(other))

        coords = [simplify(a + b) for a, b in zip(s, o)]
        return Point(coords, evaluate=False)
コード例 #14
0
ファイル: line3d.py プロジェクト: helpin/sympy
    def projection(self, o):
        """Project a point, line, ray, or segment onto this linear entity.

        Parameters
        ==========

        other : Point or LinearEntity (Line, Ray, Segment)

        Returns
        =======

        projection : Point or LinearEntity (Line, Ray, Segment)
            The return type matches the type of the parameter ``other``.

        Raises
        ======

        GeometryError
            When method is unable to perform projection.

        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 point is the intersection
        of L and the line perpendicular to L that passes through P.

        See Also
        ========

        sympy.geometry.point.Point3D, perpendicular_line

        Examples
        ========

        >>> from sympy import Point3D, Line3D, Segment3D, Rational
        >>> p1, p2, p3 = Point3D(0, 0, 1), Point3D(1, 1, 2), Point3D(2, 0, 1)
        >>> l1 = Line3D(p1, p2)
        >>> l1.projection(p3)
        Point3D(2/3, 2/3, 5/3)

        >>> p4, p5 = Point3D(10, 0, 1), Point3D(12, 1, 3)
        >>> s1 = Segment3D(p4, p5)
        >>> l1.projection(s1)
        [Segment3D(Point3D(10/3, 10/3, 13/3), Point3D(5, 5, 6))]

        """
        tline = Line3D(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, Point3D):
            return _project(o)
        elif isinstance(o, LinearEntity3D):
            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 self.intersection(projected)
コード例 #15
0
ファイル: line.py プロジェクト: Jerryy/sympy
    def projection(self, o):
        """Project a point, line, ray, or segment onto this linear entity.

        Parameters
        ----------
        other : Point or LinearEntity (Line, Ray, Segment)

        Returns
        -------
        projection : Point or LinearEntity (Line, Ray, Segment)
            The return type matches the type of the parameter `other`.

        Raises
        ------
        GeometryError
            When method is unable to perform projection.

        See Also
        --------
        Point

        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.

        Examples
        --------
        >>> from sympy import Point, Line, Segment, Rational
        >>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(Rational(1, 2), 0)
        >>> l1 = Line(p1, p2)
        >>> l1.projection(p3)
        Point(1/4, 1/4)

        >>> p4, p5 = Point(10, 0), Point(12, 1)
        >>> s1 = Segment(p4, p5)
        >>> l1.projection(s1)
        Segment(Point(5, 5), Point(13/2, 13/2))

        """
        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 self.intersection(projected)[0]
コード例 #16
0
    def random_point(self, seed=None):
        """A random point on the ellipse.

        Returns
        =======

        point : Point

        See Also
        ========

        sympy.geometry.point.Point
        arbitrary_point : Returns parameterized point on ellipse

        Notes
        -----

        A random point may not appear to be on the ellipse, ie, `p in e` may
        return False. This is because the coordinates of the point will be
        floating point values, and when these values are substituted into the
        equation for the ellipse the result may not be zero because of floating
        point rounding error.

        Examples
        ========

        >>> from sympy import Point, Ellipse, Segment
        >>> e1 = Ellipse(Point(0, 0), 3, 2)
        >>> e1.random_point() # gives some random point
        Point2D(...)
        >>> p1 = e1.random_point(seed=0); p1.n(2)
        Point2D(2.1, 1.4)

        The random_point method assures that the point will test as being
        in the ellipse:

        >>> p1 in e1
        True

        Notes
        =====

        An arbitrary_point with a random value of t substituted into it may
        not test as being on the ellipse because the expression tested that
        a point is on the ellipse doesn't simplify to zero and doesn't evaluate
        exactly to zero:

        >>> from sympy.abc import t
        >>> e1.arbitrary_point(t)
        Point2D(3*cos(t), 2*sin(t))
        >>> p2 = _.subs(t, 0.1)
        >>> p2 in e1
        False

        Note that arbitrary_point routine does not take this approach. A value
        for cos(t) and sin(t) (not t) is substituted into the arbitrary point.
        There is a small chance that this will give a point that will not
        test as being in the ellipse, so the process is repeated (up to 10
        times) until a valid point is obtained.

        """
        from sympy import sin, cos, Rational
        t = _symbol('t')
        x, y = self.arbitrary_point(t).args
        # get a random value in [-1, 1) corresponding to cos(t)
        # and confirm that it will test as being in the ellipse
        if seed is not None:
            rng = random.Random(seed)
        else:
            rng = random
        for i in range(10):  # should be enough?
            # simplify this now or else the Float will turn s into a Float
            c = 2 * Rational(rng.random()) - 1
            s = sqrt(1 - c**2)
            p1 = Point(x.subs(cos(t), c), y.subs(sin(t), s))
            if p1 in self:
                return p1
        raise GeometryError(
            'Having problems generating a point in the ellipse.')
コード例 #17
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
        got = set()
        shared = set()
        for p in nodup:
            if p in got:
                shared.add(p)
            else:
                got.add(p)
        i = -3
        while i < len(nodup) - 3 and len(nodup) > 2:
            a, b, c = sorted([nodup[i], nodup[i + 1], nodup[i + 2]])
            if b not in shared and 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:
            rv = GeometryEntity.__new__(cls, *vertices, **kwargs)
        elif len(vertices) == 3:
            return Triangle(*vertices, **kwargs)
        elif len(vertices) == 2:
            return Segment(*vertices, **kwargs)
        else:
            return Point(*vertices, **kwargs)

        # reject polygons that have intersecting sides unless the
        # intersection is a shared point or a generalized intersection.
        # A self-intersecting polygon is easier to detect than a
        # random set of segments since only those sides that are not
        # part of the convex hull can possibly intersect with other
        # sides of the polygon...but for now we use the n**2 algorithm
        # and check all sides with intersection with any preceding sides
        hit = _symbol('hit')
        if not rv.is_convex:
            sides = rv.sides
            for i, si in enumerate(sides):
                pts = si[0], si[1]
                ai = si.arbitrary_point(hit)
                for j in xrange(i):
                    sj = sides[j]
                    if sj[0] not in pts and sj[1] not in pts:
                        aj = si.arbitrary_point(hit)
                        tx = (solve(ai[0] - aj[0]) or [S.Zero])[0]
                        if tx.is_number and 0 <= tx <= 1:
                            ty = (solve(ai[1] - aj[1]) or [S.Zero])[0]
                            if (tx or ty) and ty.is_number and 0 <= ty <= 1:
                                print ai, aj
                                raise GeometryError(
                                    "Polygon has intersecting sides.")

        return rv