Пример #1
0
    def subtract_and_intersect_circle(self, center, radius):
        '''Will throw a VennRegionException if the circle to be subtracted is completely inside and not touching the given region.'''

        # Check whether the target circle intersects us
        center = np.asarray(center, float)
        d = np.linalg.norm(center - self.center)
        if d > (radius + self.radius - tol):
            return [self,
                    VennEmptyRegion()]  # The circle does not intersect us
        elif d < tol:
            if radius > self.radius - tol:
                # We are completely covered by that circle or we are the same circle
                return [VennEmptyRegion(), self]
            else:
                # That other circle is inside us and smaller than us - we can't deal with it
                raise VennRegionException(
                    "Invalid configuration of circular regions (holes are not supported)."
                )
        else:
            # We *must* intersect the other circle. If it is not the case, then it is inside us completely,
            # and we'll complain.
            intersections = circle_circle_intersection(self.center,
                                                       self.radius, center,
                                                       radius)

            if intersections is None:
                raise VennRegionException(
                    "Invalid configuration of circular regions (holes are not supported)."
                )
            elif np.all(abs(intersections[0] -
                            intersections[1]) < tol) and self.radius < radius:
                # There is a single intersection point (i.e. we are touching the circle),
                # the circle to be subtracted is not outside of us (this was checked before), and is larger than us.
                # This is a particular corner case that is not dealt with correctly by the general-purpose code below and must
                # be handled separately
                return [VennEmptyRegion(), self]
            else:
                # Otherwise the subtracted region is a 2-arc-gon
                # Before we need to convert the intersection points as angles wrt each circle.
                a_1 = vector_angle_in_degrees(intersections[0] - self.center)
                a_2 = vector_angle_in_degrees(intersections[1] - self.center)
                b_1 = vector_angle_in_degrees(intersections[0] - center)
                b_2 = vector_angle_in_degrees(intersections[1] - center)

                # We must take care of the situation where the intersection points happen to be the same
                if (abs(b_1 - b_2) < tol):
                    b_1 = b_2 - tol / 2
                if (abs(a_1 - a_2) < tol):
                    a_2 = a_1 + tol / 2

                # The subtraction is a 2-arc-gon [(AB, B-), (BA, A+)]
                s_arc1 = Arc(center, radius, b_1, b_2, False)
                s_arc2 = Arc(self.center, self.radius, a_2, a_1, True)
                subtraction = VennArcgonRegion([s_arc1, s_arc2])

                # .. and the intersection is a 2-arc-gon [(AB, A+), (BA, B+)]
                i_arc1 = Arc(self.center, self.radius, a_1, a_2, True)
                i_arc2 = Arc(center, radius, b_2, b_1, True)
                intersection = VennArcgonRegion([i_arc1, i_arc2])
                return [subtraction, intersection]
Пример #2
0
    def subtract_and_intersect_circle(self, center, radius):
        '''Will throw a VennRegionException if the circle to be subtracted is completely inside and not touching the given region.'''
        
        # Check whether the target circle intersects us
        center = np.asarray(center, float)
        d = np.linalg.norm(center - self.center)
        if d > (radius + self.radius - tol):
            return [self, VennEmptyRegion()] # The circle does not intersect us
        elif d < tol:
            if radius > self.radius - tol:
                # We are completely covered by that circle or we are the same circle
                return [VennEmptyRegion(), self]
            else:
                # That other circle is inside us and smaller than us - we can't deal with it
                raise VennRegionException("Invalid configuration of circular regions (holes are not supported).")
        else:
            # We *must* intersect the other circle. If it is not the case, then it is inside us completely,
            # and we'll complain.            
            intersections = circle_circle_intersection(self.center, self.radius, center, radius)
            
            if intersections is None:
                raise VennRegionException("Invalid configuration of circular regions (holes are not supported).")
            elif np.all(abs(intersections[0] - intersections[1]) < tol) and self.radius < radius:
                # There is a single intersection point (i.e. we are touching the circle),
                # the circle to be subtracted is not outside of us (this was checked before), and is larger than us.
                # This is a particular corner case that is not dealt with correctly by the general-purpose code below and must
                # be handled separately
                return [VennEmptyRegion(), self]
            else:
                # Otherwise the subtracted region is a 2-arc-gon
                # Before we need to convert the intersection points as angles wrt each circle.
                a_1 = vector_angle_in_degrees(intersections[0] - self.center)
                a_2 = vector_angle_in_degrees(intersections[1] - self.center)
                b_1 = vector_angle_in_degrees(intersections[0] - center)
                b_2 = vector_angle_in_degrees(intersections[1] - center)

                # We must take care of the situation where the intersection points happen to be the same
                if (abs(b_1 - b_2) < tol):
                    b_1 = b_2 - tol/2
                if (abs(a_1 - a_2) < tol):
                    a_2 = a_1 + tol/2
                
                # The subtraction is a 2-arc-gon [(AB, B-), (BA, A+)]
                s_arc1 = Arc(center, radius, b_1, b_2, False)
                s_arc2 = Arc(self.center, self.radius, a_2, a_1, True)                
                subtraction = VennArcgonRegion([s_arc1, s_arc2])
                
                # .. and the intersection is a 2-arc-gon [(AB, A+), (BA, B+)]
                i_arc1 = Arc(self.center, self.radius, a_1, a_2, True)
                i_arc2 = Arc(center, radius, b_2, b_1, True)
                intersection = VennArcgonRegion([i_arc1, i_arc2])
                return [subtraction, intersection]
Пример #3
0
 def point_as_angle(self, pt):
     '''
     Given a point located on the arc's circle, return the corresponding angle in degrees.
     No check is done that the point lies on the circle
     (this is essentially a convenience wrapper around _math.vector_angle_in_degrees)
     
     >>> a = Arc((0, 0), 1, 0, 0, True)
     >>> a.point_as_angle((1, 0))
     0.0
     >>> a.point_as_angle((1, 1))
     45.0
     >>> a.point_as_angle((0, 1))
     90.0
     >>> a.point_as_angle((-1, 1))
     135.0
     >>> a.point_as_angle((-1, 0))
     180.0
     >>> a.point_as_angle((-1, -1))
     -135.0
     >>> a.point_as_angle((0, -1))
     -90.0
     >>> a.point_as_angle((1, -1))
     -45.0
     '''
     return vector_angle_in_degrees(np.asarray(pt) - self.center)
Пример #4
0
 def point_as_angle(self, pt):
     '''
     Given a point located on the arc's circle, return the corresponding angle in degrees.
     No check is done that the point lies on the circle
     (this is essentially a convenience wrapper around _math.vector_angle_in_degrees)
     
     >>> a = Arc((0, 0), 1, 0, 0, True)
     >>> a.point_as_angle((1, 0))
     0.0
     >>> a.point_as_angle((1, 1))
     45.0
     >>> a.point_as_angle((0, 1))
     90.0
     >>> a.point_as_angle((-1, 1))
     135.0
     >>> a.point_as_angle((-1, 0))
     180.0
     >>> a.point_as_angle((-1, -1))
     -135.0
     >>> a.point_as_angle((0, -1))
     -90.0
     >>> a.point_as_angle((1, -1))
     -45.0
     '''
     return vector_angle_in_degrees(np.asarray(pt) - self.center)
Пример #5
0
    def subtract_and_intersect_circle(self, center, radius):
        '''
        Circle subtraction / intersection only supported by 2-gon regions, otherwise a VennRegionException is thrown.
        In addition, such an exception will be thrown if the circle to be subtracted is completely within the region and forms a "hole".
        
        The result may be either a VennArcgonRegion or a VennMultipieceRegion (the latter happens when the circle "splits" a crescent in two).
        '''
        if len(self.arcs) != 2:
            raise VennRegionException(
                "Circle subtraction and intersection with poly-arc regions is currently only supported for 2-arc-gons."
            )

        # In the following we consider the 2-arc-gon case.
        # Before we do anything, we check for a special case, where the circle of interest is one of the two circles forming the arcs.
        # In this case we can determine the answer quite easily.
        matching_arcs = [
            a for a in self.arcs if a.lies_on_circle(center, radius)
        ]
        if len(matching_arcs) != 0:
            # If the circle matches a positive arc, the result is [empty, self], otherwise [self, empty]
            return [VennEmptyRegion(), self
                    ] if matching_arcs[0].direction else [
                        self, VennEmptyRegion()
                    ]

        # Consider the intersection points of the circle with the arcs.
        # If any of the intersection points corresponds exactly to any of the arc's endpoints, we will end up with
        # a lot of messy special cases (as if the usual situation is not messy enough, eh).
        # To avoid that, we cheat by slightly increasing the circle's radius until this is not the case any more.
        center = np.asarray(center)
        illegal_intersections = [a.start_point() for a in self.arcs]
        while True:
            valid = True
            intersections = [
                a.intersect_circle(center, radius) for a in self.arcs
            ]
            for ints in intersections:
                for pt in ints:
                    for illegal_pt in illegal_intersections:
                        if np.all(abs(pt - illegal_pt) < tol):
                            valid = False
            if valid:
                break
            else:
                radius += tol

        # There must be an even number of those points in total.
        # (If this is not the case, then we have an unfortunate case with weird numeric errors [TODO: find examples and deal with it?]).
        # There are three possibilities with the following subcases:
        #   I. No intersection points
        #       a) The polyarc is completely within the circle.
        #           result = [ empty, self ]
        #       b) The polyarc is completely outside the circle.
        #           result = [ self, empty ]
        #   II. Four intersection points, two for each arc. Points x1, x2 for arc X and y1, y2 for arc Y, ordered along the arc.
        #       a) The polyarc endpoints are both outside the circle.
        #           result_subtraction = a combination of two 3-arc polyarcs:
        #               1: {X - start to x1,
        #                   x1 to y2 along circle (negative direction)),
        #                   Y - y2 to end}
        #               2: {Y start to y1,
        #                   y1 to x2 along circle (negative direction)),
        #                   X - x2 to end}
        #       b) The polyarc endpoints are both inside the circle
        #               same as above, but the "along circle" arc directions are flipped and subtraction/intersection parts are exchanged
        #   III. Two intersection points
        #       a) One arc, X, has two intersection points i & j, another arc, Y, has no intersection points
        #           a.1) Polyarc endpoints are outside the circle
        #               result_subtraction = {X from start to i, circle i to j (direction = negative), X j to end, Y}
        #               result_intersection = {X i to j, circle j to i (direction = positive}
        #           a.2) Polyarc endpoints are inside the circle
        #               result_subtraction = {X i to j, circle j to i negative}
        #               result_intersection = {X 0 to i, circle i to j positive, X j to end, Y}
        #       b) Both arcs, X and Y, have one intersection point each. In this case one of the arc endpoints must be inside circle, another outside.
        #          call the arc that starts with the outside point X, the other arc Y.
        #           result_subtraction = {X start to intersection, intersection to intersection along circle (negative direction), Y from intersection to end}
        #           result_intersection = {X intersection to end, Y start to intersecton, intersection to intersecion along circle (positive)}
        center = np.asarray(center)
        intersections = [a.intersect_circle(center, radius) for a in self.arcs]

        if len(intersections[0]) == 0 and len(intersections[1]) == 0:
            # Case I
            if point_in_circle(self.arcs[0].start_point(), center, radius):
                # Case I.a)
                return [VennEmptyRegion(), self]
            else:
                # Case I.b)
                return [self, VennEmptyRegion()]
        elif len(intersections[0]) == 2 and len(intersections[1]) == 2:
            # Case II. a) or b)
            case_II_a = not point_in_circle(self.arcs[0].start_point(), center,
                                            radius)

            a1 = self.arcs[0].subarc_between_points(None, intersections[0][0])
            a2 = Arc(center, radius,
                     vector_angle_in_degrees(intersections[0][0] - center),
                     vector_angle_in_degrees(intersections[1][1] - center),
                     not case_II_a)
            a2.fix_360_to_0()
            a3 = self.arcs[1].subarc_between_points(intersections[1][1], None)
            piece1 = VennArcgonRegion([a1, a2, a3])

            b1 = self.arcs[1].subarc_between_points(None, intersections[1][0])
            b2 = Arc(center, radius,
                     vector_angle_in_degrees(intersections[1][0] - center),
                     vector_angle_in_degrees(intersections[0][1] - center),
                     not case_II_a)
            b2.fix_360_to_0()
            b3 = self.arcs[0].subarc_between_points(intersections[0][1], None)
            piece2 = VennArcgonRegion([b1, b2, b3])

            subtraction = VennMultipieceRegion([piece1, piece2])

            c1 = self.arcs[0].subarc(a1.to_angle, b3.from_angle)
            c2 = b2.reversed()
            c3 = self.arcs[1].subarc(b1.to_angle, a3.from_angle)
            c4 = a2.reversed()
            intersection = VennArcgonRegion([c1, c2, c3, c4])

            return [subtraction, intersection
                    ] if case_II_a else [intersection, subtraction]
        else:
            # Case III. Yuck.
            if len(intersections[0]) == 0 or len(intersections[1]) == 0:
                # Case III.a)
                x = 0 if len(intersections[0]) != 0 else 1
                y = 1 - x
                if len(intersections[x]) != 2:
                    warnings.warn(
                        "Numeric precision error during polyarc intersection, case IIIa. Expect wrong results."
                    )
                    intersections[x] = [
                        intersections[x][0], intersections[x][0]
                    ]  # This way we'll at least produce some result, although it will probably be wrong
                if not point_in_circle(self.arcs[0].start_point(), center,
                                       radius):
                    # Case III.a.1)
                    #   result_subtraction = {X from start to i, circle i to j (direction = negative), X j to end, Y}
                    a1 = self.arcs[x].subarc_between_points(
                        None, intersections[x][0])
                    a2 = Arc(
                        center, radius,
                        vector_angle_in_degrees(intersections[x][0] - center),
                        vector_angle_in_degrees(intersections[x][1] - center),
                        False)
                    a3 = self.arcs[x].subarc_between_points(
                        intersections[x][1], None)
                    a4 = self.arcs[y]
                    subtraction = VennArcgonRegion([a1, a2, a3, a4])

                    #   result_intersection = {X i to j, circle j to i (direction = positive)}
                    b1 = self.arcs[x].subarc(a1.to_angle, a3.from_angle)
                    b2 = a2.reversed()
                    intersection = VennArcgonRegion([b1, b2])

                    return [subtraction, intersection]
                else:
                    # Case III.a.2)
                    #   result_subtraction = {X i to j, circle j to i negative}
                    a1 = self.arcs[x].subarc_between_points(
                        intersections[x][0], intersections[x][1])
                    a2 = Arc(
                        center, radius,
                        vector_angle_in_degrees(intersections[x][1] - center),
                        vector_angle_in_degrees(intersections[x][0] - center),
                        False)
                    subtraction = VennArcgonRegion([a1, a2])

                    #   result_intersection = {X 0 to i, circle i to j positive, X j to end, Y}
                    b1 = self.arcs[x].subarc(None, a1.from_angle)
                    b2 = a2.reversed()
                    b3 = self.arcs[x].subarc(a1.to_angle, None)
                    b4 = self.arcs[y]
                    intersection = VennArcgonRegion([b1, b2, b3, b4])

                    return [subtraction, intersection]
            else:
                # Case III.b)
                if len(intersections[0]) == 2 or len(intersections[1]) == 2:
                    warnings.warn(
                        "Numeric precision error during polyarc intersection, case IIIb. Expect wrong results."
                    )

                # One of the arcs must start outside the circle, call it x
                x = 0 if not point_in_circle(self.arcs[0].start_point(),
                                             center, radius) else 1
                y = 1 - x

                a1 = self.arcs[x].subarc_between_points(
                    None, intersections[x][0])
                a2 = Arc(center, radius,
                         vector_angle_in_degrees(intersections[x][0] - center),
                         vector_angle_in_degrees(intersections[y][0] - center),
                         False)
                a3 = self.arcs[y].subarc_between_points(
                    intersections[y][0], None)
                subtraction = VennArcgonRegion([a1, a2, a3])

                b1 = self.arcs[x].subarc(a1.to_angle, None)
                b2 = self.arcs[y].subarc(None, a3.from_angle)
                b3 = a2.reversed()
                intersection = VennArcgonRegion([b1, b2, b3])
                return [subtraction, intersection]
Пример #6
0
    def subtract_and_intersect_circle(self, center, radius):
        '''
        Circle subtraction / intersection only supported by 2-gon regions, otherwise a VennRegionException is thrown.
        In addition, such an exception will be thrown if the circle to be subtracted is completely within the region and forms a "hole".
        
        The result may be either a VennArcgonRegion or a VennMultipieceRegion (the latter happens when the circle "splits" a crescent in two).
        '''
        if len(self.arcs) != 2:
            raise VennRegionException("Circle subtraction and intersection with poly-arc regions is currently only supported for 2-arc-gons.")
        
        # In the following we consider the 2-arc-gon case.
        # Before we do anything, we check for a special case, where the circle of interest is one of the two circles forming the arcs.
        # In this case we can determine the answer quite easily.
        matching_arcs = [a for a in self.arcs if a.lies_on_circle(center, radius)]
        if len(matching_arcs) != 0:
            # If the circle matches a positive arc, the result is [empty, self], otherwise [self, empty]
            return [VennEmptyRegion(), self] if matching_arcs[0].direction else [self, VennEmptyRegion()]
            
        # Consider the intersection points of the circle with the arcs.
        # If any of the intersection points corresponds exactly to any of the arc's endpoints, we will end up with
        # a lot of messy special cases (as if the usual situation is not messy enough, eh).
        # To avoid that, we cheat by slightly increasing the circle's radius until this is not the case any more.
        center = np.asarray(center)
        illegal_intersections = [a.start_point() for a in self.arcs]
        while True:
            valid = True
            intersections = [a.intersect_circle(center, radius) for a in self.arcs]
            for ints in intersections:
                for pt in ints:
                    for illegal_pt in illegal_intersections:
                        if np.all(abs(pt - illegal_pt) < tol):
                            valid = False
            if valid:
                break
            else:
                radius += tol
                

        # There must be an even number of those points in total.
        # (If this is not the case, then we have an unfortunate case with weird numeric errors [TODO: find examples and deal with it?]).
        # There are three possibilities with the following subcases:
        #   I. No intersection points
        #       a) The polyarc is completely within the circle.
        #           result = [ empty, self ]
        #       b) The polyarc is completely outside the circle.
        #           result = [ self, empty ]
        #   II. Four intersection points, two for each arc. Points x1, x2 for arc X and y1, y2 for arc Y, ordered along the arc.
        #       a) The polyarc endpoints are both outside the circle.
        #           result_subtraction = a combination of two 3-arc polyarcs:
        #               1: {X - start to x1,
        #                   x1 to y2 along circle (negative direction)),
        #                   Y - y2 to end}
        #               2: {Y start to y1,
        #                   y1 to x2 along circle (negative direction)),
        #                   X - x2 to end}
        #       b) The polyarc endpoints are both inside the circle
        #               same as above, but the "along circle" arc directions are flipped and subtraction/intersection parts are exchanged
        #   III. Two intersection points
        #       a) One arc, X, has two intersection points i & j, another arc, Y, has no intersection points
        #           a.1) Polyarc endpoints are outside the circle
        #               result_subtraction = {X from start to i, circle i to j (direction = negative), X j to end, Y}
        #               result_intersection = {X i to j, circle j to i (direction = positive}
        #           a.2) Polyarc endpoints are inside the circle
        #               result_subtraction = {X i to j, circle j to i negative}
        #               result_intersection = {X 0 to i, circle i to j positive, X j to end, Y}
        #       b) Both arcs, X and Y, have one intersection point each. In this case one of the arc endpoints must be inside circle, another outside.
        #          call the arc that starts with the outside point X, the other arc Y.
        #           result_subtraction = {X start to intersection, intersection to intersection along circle (negative direction), Y from intersection to end}
        #           result_intersection = {X intersection to end, Y start to intersecton, intersection to intersecion along circle (positive)}
        center = np.asarray(center)
        intersections = [a.intersect_circle(center, radius) for a in self.arcs]
        
        if len(intersections[0]) == 0 and len(intersections[1]) == 0:
            # Case I
            if point_in_circle(self.arcs[0].start_point(), center, radius):
                # Case I.a)
                return [VennEmptyRegion(), self]
            else:
                # Case I.b)
                return [self, VennEmptyRegion()]
        elif len(intersections[0]) == 2 and len(intersections[1]) == 2:
            # Case II. a) or b)
            case_II_a = not point_in_circle(self.arcs[0].start_point(), center, radius)
            
            a1 = self.arcs[0].subarc_between_points(None, intersections[0][0])
            a2 = Arc(center, radius,
                     vector_angle_in_degrees(intersections[0][0] - center),
                     vector_angle_in_degrees(intersections[1][1] - center),
                     not case_II_a)
            a2.fix_360_to_0()
            a3 = self.arcs[1].subarc_between_points(intersections[1][1], None)
            piece1 = VennArcgonRegion([a1, a2, a3])
            
            b1 = self.arcs[1].subarc_between_points(None, intersections[1][0])
            b2 = Arc(center, radius,
                     vector_angle_in_degrees(intersections[1][0] - center),
                     vector_angle_in_degrees(intersections[0][1] - center),
                     not case_II_a)
            b2.fix_360_to_0()
            b3 = self.arcs[0].subarc_between_points(intersections[0][1], None)
            piece2 = VennArcgonRegion([b1, b2, b3])
            
            subtraction = VennMultipieceRegion([piece1, piece2])
            
            c1 = self.arcs[0].subarc(a1.to_angle, b3.from_angle)
            c2 = b2.reversed()
            c3 = self.arcs[1].subarc(b1.to_angle, a3.from_angle)
            c4 = a2.reversed()
            intersection = VennArcgonRegion([c1, c2, c3, c4])
            
            return [subtraction, intersection] if case_II_a else [intersection, subtraction]
        else:
            # Case III. Yuck.
            if len(intersections[0]) == 0 or len(intersections[1]) == 0:
                # Case III.a)
                x = 0 if len(intersections[0]) != 0 else 1
                y = 1 - x
                if len(intersections[x]) != 2:
                    warnings.warn("Numeric precision error during polyarc intersection, case IIIa. Expect wrong results.")
                    intersections[x] = [intersections[x][0], intersections[x][0]]  # This way we'll at least produce some result, although it will probably be wrong
                if not point_in_circle(self.arcs[0].start_point(), center, radius):
                    # Case III.a.1)
                    #   result_subtraction = {X from start to i, circle i to j (direction = negative), X j to end, Y}
                    a1 = self.arcs[x].subarc_between_points(None, intersections[x][0])
                    a2 = Arc(center, radius,
                             vector_angle_in_degrees(intersections[x][0] - center),
                             vector_angle_in_degrees(intersections[x][1] - center),
                             False)
                    a3 = self.arcs[x].subarc_between_points(intersections[x][1], None)
                    a4 = self.arcs[y]
                    subtraction = VennArcgonRegion([a1, a2, a3, a4])
                    
                    #   result_intersection = {X i to j, circle j to i (direction = positive)}
                    b1 = self.arcs[x].subarc(a1.to_angle, a3.from_angle)
                    b2 = a2.reversed()
                    intersection = VennArcgonRegion([b1, b2])
                    
                    return [subtraction, intersection]
                else:
                    # Case III.a.2)
                    #   result_subtraction = {X i to j, circle j to i negative}
                    a1 = self.arcs[x].subarc_between_points(intersections[x][0], intersections[x][1])
                    a2 = Arc(center, radius,
                             vector_angle_in_degrees(intersections[x][1] - center),
                             vector_angle_in_degrees(intersections[x][0] - center),
                             False)
                    subtraction = VennArcgonRegion([a1, a2])
                    
                    #   result_intersection = {X 0 to i, circle i to j positive, X j to end, Y}
                    b1 = self.arcs[x].subarc(None, a1.from_angle)
                    b2 = a2.reversed()
                    b3 = self.arcs[x].subarc(a1.to_angle, None)
                    b4 = self.arcs[y]
                    intersection = VennArcgonRegion([b1, b2, b3, b4])
                    
                    return [subtraction, intersection]
            else:
                # Case III.b)
                if len(intersections[0]) == 2 or len(intersections[1]) == 2:
                    warnings.warn("Numeric precision error during polyarc intersection, case IIIb. Expect wrong results.")
                
                # One of the arcs must start outside the circle, call it x
                x = 0 if not point_in_circle(self.arcs[0].start_point(), center, radius) else 1
                y = 1 - x
                
                a1 = self.arcs[x].subarc_between_points(None, intersections[x][0])
                a2 = Arc(center, radius,
                         vector_angle_in_degrees(intersections[x][0] - center),
                         vector_angle_in_degrees(intersections[y][0] - center), False)
                a3 = self.arcs[y].subarc_between_points(intersections[y][0], None)
                subtraction = VennArcgonRegion([a1, a2, a3])
                
                b1 = self.arcs[x].subarc(a1.to_angle, None)
                b2 = self.arcs[y].subarc(None, a3.from_angle)
                b3 = a2.reversed()
                intersection = VennArcgonRegion([b1, b2, b3])
                return [subtraction, intersection]