def compute_venn2_regions(centers, radii):
    '''
    Returns a triple of VennRegion objects, describing the three regions of the diagram, corresponding to sets
    (Ab, aB, AB)

    >>> centers, radii = solve_venn2_circles((1, 1, 0.5))
    >>> regions = compute_venn2_regions(centers, radii)
    '''
    A = VennCircleRegion(centers[0], radii[0])
    B = VennCircleRegion(centers[1], radii[1])
    Ab, AB = A.subtract_and_intersect_circle(B.center, B.radius)
    aB, _ = B.subtract_and_intersect_circle(A.center, A.radius)
    return (Ab, aB, AB)
Exemple #2
0
def compute_venn3_regions(centers, radii):
    '''
    Given the 3x2 matrix with circle center coordinates, and a 3-element list (or array) with circle radii [as returned from solve_venn3_circles],
    returns the 7 regions, comprising the venn diagram, as VennRegion objects.

    Regions are returned in order (Abc, aBc, ABc, abC, AbC, aBC, ABC)

    >>> centers, radii = solve_venn3_circles((1, 1, 1, 1, 1, 1, 1))
    >>> regions = compute_venn3_regions(centers, radii)
    '''
    A = VennCircleRegion(centers[0], radii[0])
    B = VennCircleRegion(centers[1], radii[1])
    C = VennCircleRegion(centers[2], radii[2])
    Ab, AB = A.subtract_and_intersect_circle(B.center, B.radius)
    ABc, ABC = AB.subtract_and_intersect_circle(C.center, C.radius)
    Abc, AbC = Ab.subtract_and_intersect_circle(C.center, C.radius)
    aB, _ = B.subtract_and_intersect_circle(A.center, A.radius)
    aBc, aBC = aB.subtract_and_intersect_circle(C.center, C.radius)
    aC, _ = C.subtract_and_intersect_circle(A.center, A.radius)
    abC, _ = aC.subtract_and_intersect_circle(B.center, B.radius)
    return [Abc, aBc, ABc, abC, AbC, aBC, ABC]
def compute_venn2_regions(centers, radii):
    """
    Returns a triple of VennRegion objects, describing the three regions of the diagram, corresponding to sets
    (Ab, aB, AB)

    >>> centers, radii = solve_venn2_circles((1, 1, 0.5))
    >>> regions = compute_venn2_regions(centers, radii)
    """
    A = VennCircleRegion(centers[0], radii[0])
    B = VennCircleRegion(centers[1], radii[1])
    Ab, AB = A.subtract_and_intersect_circle(B.center, B.radius)
    aB, _ = B.subtract_and_intersect_circle(A.center, A.radius)
    return Ab, aB, AB
def compute_venn3_regions(centers, radii):
    '''
    Given the 3x2 matrix with circle center coordinates, and a 3-element list (or array) with circle radii [as returned from solve_venn3_circles],
    returns the 7 regions, comprising the venn diagram, as VennRegion objects.
    Regions are returned in order (Abc, aBc, ABc, abC, AbC, aBC, ABC)
    >>> centers, radii = solve_venn3_circles((1, 1, 1, 1, 1, 1, 1))
    >>> regions = compute_venn3_regions(centers, radii)
    '''
    A = VennCircleRegion(centers[0], radii[0])
    B = VennCircleRegion(centers[1], radii[1])
    C = VennCircleRegion(centers[2], radii[2])
    Ab, AB = A.subtract_and_intersect_circle(B.center, B.radius)
    ABc, ABC = AB.subtract_and_intersect_circle(C.center, C.radius)
    Abc, AbC = Ab.subtract_and_intersect_circle(C.center, C.radius)
    aB, _ = B.subtract_and_intersect_circle(A.center, A.radius)
    aBc, aBC = aB.subtract_and_intersect_circle(C.center, C.radius)
    aC, _ = C.subtract_and_intersect_circle(A.center, A.radius)
    abC, _ = aC.subtract_and_intersect_circle(B.center, B.radius)
    return [Abc, aBc, ABc, abC, AbC, aBC, ABC]
def test_circle_region():
    with pytest.raises(VennRegionException):
        vcr = VennCircleRegion((0, 0), -1)
        
    vcr = VennCircleRegion((0, 0), 10)
    assert abs(vcr.size() - np.pi*100) <= tol
    
    # Interact with non-intersecting circle
    sr, ir = vcr.subtract_and_intersect_circle((11, 1), 1)
    assert sr == vcr
    assert ir.is_empty()
    
    # Interact with self
    sr, ir = vcr.subtract_and_intersect_circle((0, 0), 10)
    assert sr.is_empty()
    assert ir == vcr
    
    # Interact with a circle that makes a hole
    with pytest.raises(VennRegionException):
        sr, ir = vcr.subtract_and_intersect_circle((0, 8.9), 1)
    
    # Interact with a circle that touches the side from the inside
    for (a, r) in [(0, 1), (90, 2), (180, 3), (290, 0.01), (42, 9.99), (-0.1, 9.999), (180.1, 0.001)]:
        cx = np.cos(a * np.pi / 180.0) * (10 - r)
        cy = np.sin(a * np.pi / 180.0) * (10 - r)
        #print "Next test case", a, r, cx, cy, r
        TEST_TOLERANCE = tol if r > 0.001 and r < 9.999 else 1e-4 # For tricky circles the numeric errors for arc lengths are just too big here
        
        sr, ir = vcr.subtract_and_intersect_circle((cx, cy), r)
        sr.verify()
        ir.verify()
        assert len(sr.arcs) == 2 and len(ir.arcs) == 2
        for a in sr.arcs:
            assert abs(a.length_degrees() - 360) < TEST_TOLERANCE 
        assert abs(ir.arcs[0].length_degrees() - 0) < TEST_TOLERANCE
        assert abs(ir.arcs[1].length_degrees() - 360) < TEST_TOLERANCE
        assert abs(sr.size() + np.pi*r**2 - vcr.size()) < tol
        assert abs(ir.size() - np.pi*r**2) < tol
    
    # Interact with a circle that touches the side from the outside
    for (a, r) in [(0, 1), (90, 2), (180, 3), (290, 0.01), (42, 9.99), (-0.1, 9.999), (180.1, 0.001)]:
        cx = np.cos(a * np.pi / 180.0) * (10 + r)
        cy = np.sin(a * np.pi / 180.0) * (10 + r)
        
        sr, ir = vcr.subtract_and_intersect_circle((cx, cy), r)
        # Depending on numeric roundoff we may get either an self and VennEmptyRegion or two arc regions. In any case the sizes should match
        assert abs(sr.size() + ir.size() - vcr.size()) < tol
        if (sr == vcr):
            assert ir.is_empty()
        else:
            sr.verify()
            ir.verify()
            assert len(sr.arcs) == 2 and len(ir.arcs) == 2
            assert abs(sr.arcs[0].length_degrees() - 0) < tol
            assert abs(sr.arcs[1].length_degrees() - 360) < tol
            assert abs(ir.arcs[0].length_degrees() - 0) < tol
            assert abs(ir.arcs[1].length_degrees() - 0) < tol
            
    # Interact with some cases of intersecting circles
    for (a, r) in [(0, 1), (90, 2), (180, 3), (290, 0.01), (42, 9.99), (-0.1, 9.999), (180.1, 0.001)]:
        cx = np.cos(a * np.pi / 180.0) * 10
        cy = np.sin(a * np.pi / 180.0) * 10
        
        sr, ir = vcr.subtract_and_intersect_circle((cx, cy), r)
        sr.verify()
        ir.verify()
        assert len(sr.arcs) == 2 and len(ir.arcs) == 2
        assert abs(sr.size() + ir.size() - vcr.size()) < tol
        assert sr.size() > 0
        assert ir.size() > 0
        
        # Do intersection the other way
        vcr2 = VennCircleRegion([cx, cy], r)
        sr2, ir2 = vcr2.subtract_and_intersect_circle(vcr.center, vcr.radius)
        sr2.verify()
        ir2.verify()
        assert len(sr2.arcs) == 2 and len(ir2.arcs) == 2
        assert abs(sr2.size() + ir2.size() - vcr2.size()) < tol
        assert sr2.size() > 0
        assert ir2.size() > 0
        for i in range(2):
            assert ir.arcs[i].approximately_equal(ir.arcs[i]) 
Exemple #6
0
def test_circle_region():
    with pytest.raises(VennRegionException):
        vcr = VennCircleRegion((0, 0), -1)

    vcr = VennCircleRegion((0, 0), 10)
    assert abs(vcr.size() - np.pi * 100) <= tol

    # Interact with non-intersecting circle
    sr, ir = vcr.subtract_and_intersect_circle((11, 1), 1)
    assert sr == vcr
    assert ir.is_empty()

    # Interact with self
    sr, ir = vcr.subtract_and_intersect_circle((0, 0), 10)
    assert sr.is_empty()
    assert ir == vcr

    # Interact with a circle that makes a hole
    with pytest.raises(VennRegionException):
        sr, ir = vcr.subtract_and_intersect_circle((0, 8.9), 1)

    # Interact with a circle that touches the side from the inside
    for (a, r) in [(0, 1), (90, 2), (180, 3), (290, 0.01), (42, 9.99),
                   (-0.1, 9.999), (180.1, 0.001)]:
        cx = np.cos(a * np.pi / 180.0) * (10 - r)
        cy = np.sin(a * np.pi / 180.0) * (10 - r)
        #print "Next test case", a, r, cx, cy, r
        TEST_TOLERANCE = tol if r > 0.001 and r < 9.999 else 1e-4  # For tricky circles the numeric errors for arc lengths are just too big here

        sr, ir = vcr.subtract_and_intersect_circle((cx, cy), r)
        sr.verify()
        ir.verify()
        assert len(sr.arcs) == 2 and len(ir.arcs) == 2
        for a in sr.arcs:
            assert abs(a.length_degrees() - 360) < TEST_TOLERANCE
        assert abs(ir.arcs[0].length_degrees() - 0) < TEST_TOLERANCE
        assert abs(ir.arcs[1].length_degrees() - 360) < TEST_TOLERANCE
        assert abs(sr.size() + np.pi * r**2 - vcr.size()) < tol
        assert abs(ir.size() - np.pi * r**2) < tol

    # Interact with a circle that touches the side from the outside
    for (a, r) in [(0, 1), (90, 2), (180, 3), (290, 0.01), (42, 9.99),
                   (-0.1, 9.999), (180.1, 0.001)]:
        cx = np.cos(a * np.pi / 180.0) * (10 + r)
        cy = np.sin(a * np.pi / 180.0) * (10 + r)

        sr, ir = vcr.subtract_and_intersect_circle((cx, cy), r)
        # Depending on numeric roundoff we may get either an self and VennEmptyRegion or two arc regions. In any case the sizes should match
        assert abs(sr.size() + ir.size() - vcr.size()) < tol
        if (sr == vcr):
            assert ir.is_empty()
        else:
            sr.verify()
            ir.verify()
            assert len(sr.arcs) == 2 and len(ir.arcs) == 2
            assert abs(sr.arcs[0].length_degrees() - 0) < tol
            assert abs(sr.arcs[1].length_degrees() - 360) < tol
            assert abs(ir.arcs[0].length_degrees() - 0) < tol
            assert abs(ir.arcs[1].length_degrees() - 0) < tol

    # Interact with some cases of intersecting circles
    for (a, r) in [(0, 1), (90, 2), (180, 3), (290, 0.01), (42, 9.99),
                   (-0.1, 9.999), (180.1, 0.001)]:
        cx = np.cos(a * np.pi / 180.0) * 10
        cy = np.sin(a * np.pi / 180.0) * 10

        sr, ir = vcr.subtract_and_intersect_circle((cx, cy), r)
        sr.verify()
        ir.verify()
        assert len(sr.arcs) == 2 and len(ir.arcs) == 2
        assert abs(sr.size() + ir.size() - vcr.size()) < tol
        assert sr.size() > 0
        assert ir.size() > 0

        # Do intersection the other way
        vcr2 = VennCircleRegion([cx, cy], r)
        sr2, ir2 = vcr2.subtract_and_intersect_circle(vcr.center, vcr.radius)
        sr2.verify()
        ir2.verify()
        assert len(sr2.arcs) == 2 and len(ir2.arcs) == 2
        assert abs(sr2.size() + ir2.size() - vcr2.size()) < tol
        assert sr2.size() > 0
        assert ir2.size() > 0
        for i in range(2):
            assert ir.arcs[i].approximately_equal(ir.arcs[i])