def intersection(self, o):
        if isinstance(o, Point):
            if o in self:
                return [o]
            else:
                return []

        elif isinstance(o, LinearEntity):
            a1, b1, c1 = self.coefficients
            a2, b2, c2 = o.coefficients
            t = simplify(a1*b2 - a2*b1)
            if t.equals(0) is not False:  # assume they are parallel
                if isinstance(self, Line):
                    if o.p1 in self:
                        return [o]
                    return []
                elif isinstance(o, Line):
                    if self.p1 in o:
                        return [self]
                    return []
                elif isinstance(self, Ray):
                    if isinstance(o, Ray):
                        # case 1, rays in the same direction
                        if self.xdirection == o.xdirection and \
                                self.ydirection == o.ydirection:
                            return [self] if (self.source in o) else [o]
                        # case 2, rays in the opposite directions
                        else:
                            if o.source in self:
                                if self.source == o.source:
                                    return [self.source]
                                return [Segment(o.source, self.source)]
                            return []
                    elif isinstance(o, Segment):
                        if o.p1 in self:
                            if o.p2 in self:
                                return [o]
                            return [Segment(o.p1, self.source)]
                        elif o.p2 in self:
                            return [Segment(o.p2, self.source)]
                        return []
                elif isinstance(self, Segment):
                    if isinstance(o, Ray):
                        return o.intersection(self)
                    elif isinstance(o, Segment):
                        # A reminder that the points of Segments are ordered
                        # in such a way that the following works. See
                        # Segment.__new__ for details on the ordering.
                        if self.p1 not in o:
                            if self.p2 not in o:
                                # Neither of the endpoints are in o so either
                                # o is contained in this segment or it isn't
                                if o in self:
                                    return [self]
                                return []
                            else:
                                # p1 not in o but p2 is. Either there is a
                                # segment as an intersection, or they only
                                # intersect at an endpoint
                                if self.p2 == o.p1:
                                    return [o.p1]
                                return [Segment(o.p1, self.p2)]
                        elif self.p2 not in o:
                            # p2 not in o but p1 is. Either there is a
                            # segment as an intersection, or they only
                            # intersect at an endpoint
                            if self.p1 == o.p2:
                                return [o.p2]
                            return [Segment(o.p2, self.p1)]

                        # Both points of self in o so the whole segment
                        # is in o
                        return [self]

                # Unknown linear entity
                return []

            # Not parallel, so find the point of intersection
            px = simplify((b1*c2 - c1*b2) / t)
            py = simplify((a2*c1 - a1*c2) / t)
            inter = Point(px, py)
            # we do not use a simplistic 'inter in self and inter in o'
            # because that requires an equality test that is fragile;
            # instead we employ some diagnostics to see if the intersection
            # is valid

            def inseg(self):
                def _between(a, b, c):
                    return c >= a and c <= b or c <= a and c >= b
                if _between(self.p1.x, self.p2.x, inter.x) and \
                        _between(self.p1.y, self.p2.y, inter.y):
                    return True

            def inray(self):
                if self.p1 == inter:
                    return True
                sray = Ray(self.p1, inter)
                if sray.xdirection == self.xdirection and \
                        sray.ydirection == self.ydirection:
                    return True

            prec = (Line, Ray, Segment)
            expr = self
            if prec.index(expr.func) > prec.index(o.func):
                expr, o = o, expr
            rv = [inter]
            if isinstance(expr, Line):
                if isinstance(o, Line):
                    return rv
                elif isinstance(o, Ray) and inray(o):
                    return rv
                elif isinstance(o, Segment) and inseg(o):
                    return rv
            elif isinstance(expr, Ray) and inray(expr):
                if isinstance(o, Ray) and inray(o):
                    return rv
                elif isinstance(o, Segment) and inseg(o):
                    return rv
            elif isinstance(expr, Segment) and inseg(expr):
                if isinstance(o, Segment) and inseg(o):
                    return rv
            return []

        return o.intersection(self)
The intersection with another geometrical entity.
dataset/ETHPy150Open sympy/sympy/sympy/geometry/line.py/LinearEntity.intersection