def test_arc_line_half_illegal_joint():
    p = Pen()
    p.stroke_mode(1.0)
    p.move_to((0, 0))
    p.line_to((1, 0))
    p.turn_to(180 - 15)
    p.arc_to((-1, 0))

    line, arc = p.last_path().segments
    assert line.end_joint_illegal
    assert arc.start_joint_illegal

    assert_path_data(p, 2,
                     ('M0.00,-0.50 L0.00,0.50 L2.93,0.50 '
                      'A 4.36,4.36 0 0 0 -1.13,-0.48 L-0.87,0.48 '
                      'A 3.36,3.36 0 0 1 0.87,0.48 L1.00,-0.50 L0.00,-0.50 z'))

    p = Pen()
    p.stroke_mode(1.0)
    p.move_to((-1, 0))
    p.turn_to(15)
    p.arc_to((1, 0))
    p.line_to((0, 0))

    arc, line = p.paper.paths[0].segments
    assert arc.end_joint_illegal
    assert line.start_joint_illegal

    assert_path_data(p, 2,
                     ('M-1.13,-0.48 L-0.87,0.48 A 3.36,3.36 0 0 1 0.87,0.48 '
                      'L1.00,-0.50 L0.00,-0.50 L0.00,0.50 L2.93,0.50 '
                      'A 4.36,4.36 0 0 0 -1.13,-0.48 z'))
def test_arc_angle_error():
    # Endpoints with certain angles do not go all the way across the
    # stroke, and are disallowed.
    p = Pen()
    p.stroke_mode(1.0)
    p.arc_left(90, 10, start_slant=0)
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert not seg.end_joint_illegal

    p = Pen()
    p.stroke_mode(1.0)
    p.arc_left(90, 10, end_slant=90)
    seg = p.last_segment()
    assert not seg.start_joint_illegal
    assert seg.end_joint_illegal

    p = Pen()
    p.stroke_mode(1.0)
    p.move_to((0, 0))
    p.turn_to(0)
    p.arc_left(90, radius=5, start_slant=25)
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert not seg.end_joint_illegal

    # A combination of angles can also create a degenerate arc.
    p = Pen()
    p.stroke_mode(1.0)
    p.turn_toward((1, 0))
    p.turn_left(1)
    p.arc_to((1, 0), start_slant=40, end_slant=-40)
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert seg.end_joint_illegal
def test_arc_angle_error():
    # Endpoints with certain angles do not go all the way across the
    # stroke, and are disallowed.
    p = Pen()
    p.stroke_mode(1.0)
    p.arc_left(90, 10, start_slant=0)
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert not seg.end_joint_illegal

    p = Pen()
    p.stroke_mode(1.0)
    p.arc_left(90, 10, end_slant=90)
    seg = p.last_segment()
    assert not seg.start_joint_illegal
    assert seg.end_joint_illegal

    p = Pen()
    p.stroke_mode(1.0)
    p.move_to((0, 0))
    p.turn_to(0)
    p.arc_left(90, radius=5, start_slant=25)
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert not seg.end_joint_illegal

    # A combination of angles can also create a degenerate arc.
    p = Pen()
    p.stroke_mode(1.0)
    p.turn_toward((1, 0))
    p.turn_left(1)
    p.arc_to((1, 0), start_slant=40, end_slant=-40)
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert seg.end_joint_illegal
def test_degenerate_arc():
    p = Pen()
    p.stroke_mode(2.0)

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to(
        (5, 0),
        center=(0, -200),
        start_slant=-5,
        end_slant=5,
    )
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert seg.end_joint_illegal
def test_degenerate_arc():
    p = Pen()
    p.stroke_mode(2.0)

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to(
        (5, 0),
        center=(0, -200),
        start_slant=-5,
        end_slant=5,
    )
    seg = p.last_segment()
    assert seg.start_joint_illegal
    assert seg.end_joint_illegal
def test_arc_arc_half_illegal_joint():
    p = Pen()
    p.move_to((0, -5))
    p.turn_to(0)

    p.stroke_mode(1.0)
    p.arc_to((5, 0), center=(0, 0))
    p.stroke_mode(2.0)
    p.arc_to((10, 5), center=(10, 0))

    arc1, arc2 = p.last_path().segments
    assert arc1.end_joint_illegal
    assert arc2.start_joint_illegal

    assert_path_data(
        p, 2, ('M0.00,4.50 L0.00,5.50 A 5.50,5.50 0 0 0 5.50,0.00 L6.00,0.00 '
               'A 4.00,4.00 0 0 1 10.00,-4.00 L10.00,-6.00 '
               'A 6.00,6.00 0 0 0 4.21,1.58 '
               'A 4.50,4.50 0 0 1 0.00,4.50 z'))
def test_arc_line_joint_bug():
    # When using arc_to, sometimes the b_left and b_right would get
    # reversed.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to((0, 0))
    p.turn_to(90)
    p.arc_to((5, 5))
    p.turn_to(-90)
    p.line_forward(5)

    assert_path_data(
        p, 3,
        (
            'M-0.500,0.000 L0.500,0.000 '
            'A 4.500,4.500 0 0 1 4.500,-4.472 '
            'L4.500,0.000 L5.500,0.000 L5.500,-5.477 '
            'A 5.500,5.500 0 0 0 -0.500,0.000 z'
        )
    )
def test_arc_line_joint_bug():
    # When using arc_to, sometimes the b_left and b_right would get
    # reversed.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to((0, 0))
    p.turn_to(90)
    p.arc_to((5, 5))
    p.turn_to(-90)
    p.line_forward(5)

    assert_path_data(
        p, 3,
        (
            'M-0.500,0.000 L0.500,0.000 '
            'A 4.500,4.500 0 0 1 4.500,-4.472 '
            'L4.500,0.000 L5.500,0.000 L5.500,-5.477 '
            'A 5.500,5.500 0 0 0 -0.500,0.000 z'
        )
    )
def test_arc_line_half_illegal_joint():
    p = Pen()
    p.stroke_mode(1.0)
    p.move_to((0, 0))
    p.line_to((1, 0))
    p.turn_to(180 - 15)
    p.arc_to((-1, 0))

    line, arc = p.last_path().segments
    assert line.end_joint_illegal
    assert arc.start_joint_illegal

    assert_path_data(
        p, 2,
        (
            'M0.00,-0.50 L0.00,0.50 L2.93,0.50 '
            'A 4.36,4.36 0 0 0 -1.13,-0.48 L-0.87,0.48 '
            'A 3.36,3.36 0 0 1 0.87,0.48 L1.00,-0.50 L0.00,-0.50 z'
        )
    )

    p = Pen()
    p.stroke_mode(1.0)
    p.move_to((-1, 0))
    p.turn_to(15)
    p.arc_to((1, 0))
    p.line_to((0, 0))

    arc, line = p.paper.paths[0].segments
    assert arc.end_joint_illegal
    assert line.start_joint_illegal

    assert_path_data(
        p, 2,
        (
            'M-1.13,-0.48 L-0.87,0.48 A 3.36,3.36 0 0 1 0.87,0.48 '
            'L1.00,-0.50 L0.00,-0.50 L0.00,0.50 L2.93,0.50 '
            'A 4.36,4.36 0 0 0 -1.13,-0.48 z'
        )
    )
def test_arc_start_slant_bug():
    # Some arcs are not reporting their start and end slants correctly.

    # Set up positions on a circle at angles -120 and 30
    p = Pen()
    p.fill_mode()

    p.move_to((0, 0))
    p.turn_to(30)
    p.move_forward(3)
    p1 = p.position
    p.turn_left(90)
    h1 = p.heading

    p.move_to((0, 0))
    p.turn_to(-120)
    p.move_forward(3)
    p2 = p.position

    # Create an arc using arc_left.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_left(210, 3)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading, 120)
    assert_almost_equal(arc.end_heading, 330)

    # Create the same arc using arc_to.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_to(p2)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading.theta, 120)
    assert_almost_equal(arc.end_heading.theta, 330)
def test_arc_start_slant_bug():
    # Some arcs are not reporting their start and end slants correctly.

    # Set up positions on a circle at angles -120 and 30
    p = Pen()
    p.fill_mode()

    p.move_to((0, 0))
    p.turn_to(30)
    p.move_forward(3)
    p1 = p.position
    p.turn_left(90)
    h1 = p.heading

    p.move_to((0, 0))
    p.turn_to(-120)
    p.move_forward(3)
    p2 = p.position

    # Create an arc using arc_left.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_left(210, 3)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading, 120)
    assert_almost_equal(arc.end_heading, 330)

    # Create the same arc using arc_to.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_to(p2)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading.theta, 120)
    assert_almost_equal(arc.end_heading.theta, 330)
def test_arc_no_joint():
    # Try to create an impossible joint between arcs of different widths.
    # It doesn't join.
    p = Pen()
    p.move_to((0, -5))
    p.turn_to(0)

    p.stroke_mode(1.0)
    p.arc_to((5, 0), center=(0, 0))
    p.stroke_mode(2.0)
    p.arc_to((0, 5), center=(0, 0))

    arc1, arc2 = p.last_path().segments
    assert arc1.end_joint_illegal
    assert arc2.start_joint_illegal

    assert_path_data(
        p, 1,
        (
            'M0.0,4.5 L0.0,5.5 A 5.5,5.5 0 0 0 5.5,0.0 L6.0,0.0 '
            'A 6.0,6.0 0 0 0 0.0,-6.0 L0.0,-4.0 '
            'A 4.0,4.0 0 0 1 4.0,0.0 L4.5,0.0 '
            'A 4.5,4.5 0 0 1 0.0,4.5 z'
        )
    )

    # Join two arcs together illegally, but don't make them concentric.
    p = Pen()
    p.move_to((0, -5))
    p.turn_to(0)

    p.stroke_mode(1.0)
    p.arc_to((5, 0), center=(0, 0))
    p.stroke_mode(2.0)
    p.arc_to((0, 5), center=(0, 0.1))

    arc1, arc2 = p.last_path().segments
    assert arc1.end_joint_illegal
    assert arc2.start_joint_illegal

    assert_path_data(
        p, 2,
        (
            'M0.00,4.50 L0.00,5.50 A 5.50,5.50 0 0 0 5.50,0.00 L6.00,0.02 '
            'A 6.00,6.00 0 0 0 0.00,-6.10 L0.00,-4.10 '
            'A 4.00,4.00 0 0 1 4.00,-0.02 L4.50,0.00 '
            'A 4.50,4.50 0 0 1 0.00,4.50 z'
        )
    )
def test_arc_arc_half_illegal_joint():
    p = Pen()
    p.move_to((0, -5))
    p.turn_to(0)

    p.stroke_mode(1.0)
    p.arc_to((5, 0), center=(0, 0))
    p.stroke_mode(2.0)
    p.arc_to((10, 5), center=(10, 0))

    arc1, arc2 = p.last_path().segments
    assert arc1.end_joint_illegal
    assert arc2.start_joint_illegal

    assert_path_data(
        p, 2,
        (
            'M0.00,4.50 L0.00,5.50 A 5.50,5.50 0 0 0 5.50,0.00 L6.00,0.00 '
            'A 4.00,4.00 0 0 1 10.00,-4.00 L10.00,-6.00 '
            'A 6.00,6.00 0 0 0 4.21,1.58 '
            'A 4.50,4.50 0 0 1 0.00,4.50 z'
        )
    )
def test_arc_no_joint():
    # Try to create an impossible joint between arcs of different widths.
    # It doesn't join.
    p = Pen()
    p.move_to((0, -5))
    p.turn_to(0)

    p.stroke_mode(1.0)
    p.arc_to((5, 0), center=(0, 0))
    p.stroke_mode(2.0)
    p.arc_to((0, 5), center=(0, 0))

    arc1, arc2 = p.last_path().segments
    assert arc1.end_joint_illegal
    assert arc2.start_joint_illegal

    assert_path_data(p, 1,
                     ('M0.0,4.5 L0.0,5.5 A 5.5,5.5 0 0 0 5.5,0.0 L6.0,0.0 '
                      'A 6.0,6.0 0 0 0 0.0,-6.0 L0.0,-4.0 '
                      'A 4.0,4.0 0 0 1 4.0,0.0 L4.5,0.0 '
                      'A 4.5,4.5 0 0 1 0.0,4.5 z'))

    # Join two arcs together illegally, but don't make them concentric.
    p = Pen()
    p.move_to((0, -5))
    p.turn_to(0)

    p.stroke_mode(1.0)
    p.arc_to((5, 0), center=(0, 0))
    p.stroke_mode(2.0)
    p.arc_to((0, 5), center=(0, 0.1))

    arc1, arc2 = p.last_path().segments
    assert arc1.end_joint_illegal
    assert arc2.start_joint_illegal

    assert_path_data(
        p, 2, ('M0.00,4.50 L0.00,5.50 A 5.50,5.50 0 0 0 5.50,0.00 L6.00,0.02 '
               'A 6.00,6.00 0 0 0 0.00,-6.10 L0.00,-4.10 '
               'A 4.00,4.00 0 0 1 4.00,-0.02 L4.50,0.00 '
               'A 4.50,4.50 0 0 1 0.00,4.50 z'))
def test_arc_to():
    # Make the same arcs as test_arc, but using the destination points instead
    # of the angles.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, 5))
    p.arc_to((5, 0))

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, -5))
    p.arc_to((5, 0))

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        ),
    )
def test_arc_to():
    # Make the same arcs as test_arc, but using the destination points instead
    # of the angles.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, 5))
    p.arc_to((5, 0))

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, -5))
    p.arc_to((5, 0))

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        ),
    )
def test_arc_arc_joint():
    top = (0, 5)
    left = (-2, 0)
    right = (2, 0)

    # Convex-convex.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_left(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_left(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.522,0.000 L-1.477,0.000 '
            'A 30.394,30.394 0 0 1 0.000,-3.853 '
            'A 30.394,30.394 0 0 1 1.477,0.000 '
            'L2.522,0.000 '
            'A 31.394,31.394 0 0 0 0.000,-6.076 '
            'A 31.394,31.394 0 0 0 -2.522,0.000 z'
        )
    )

    # Concave-concave.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_right(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_right(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.561,0.000 L-1.441,0.000 '
            'A 31.394,31.394 0 0 0 0.000,-3.400 '
            'A 31.394,31.394 0 0 0 1.441,0.000 '
            'L2.561,0.000 '
            'A 30.394,30.394 0 0 1 0.000,-6.923 '
            'A 30.394,30.394 0 0 1 -2.561,0.000 z'
        )
    )

    # Convex-concave.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_left(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_right(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.522,0.000 L-1.477,0.000 '
            'A 30.394,30.394 0 0 1 -0.090,-3.656 '
            'A 31.394,31.394 0 0 0 1.441,0.000 '
            'L2.561,0.000 '
            'A 30.394,30.394 0 0 1 0.144,-6.339 '
            'A 31.394,31.394 0 0 0 -2.522,0.000 z'
        )
    )

    # Concave-convex.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_right(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_left(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.561,0.000 L-1.441,0.000 '
            'A 31.394,31.394 0 0 0 0.090,-3.656 '
            'A 30.394,30.394 0 0 1 1.477,0.000 '
            'L2.522,0.000 '
            'A 31.394,31.394 0 0 0 -0.144,-6.339 '
            'A 30.394,30.394 0 0 1 -2.561,0.000 z'
        )
    )
def test_arc_arc_joint():
    top = (0, 5)
    left = (-2, 0)
    right = (2, 0)

    # Convex-convex.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_left(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_left(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.522,0.000 L-1.477,0.000 '
            'A 30.394,30.394 0 0 1 0.000,-3.853 '
            'A 30.394,30.394 0 0 1 1.477,0.000 '
            'L2.522,0.000 '
            'A 31.394,31.394 0 0 0 0.000,-6.076 '
            'A 31.394,31.394 0 0 0 -2.522,0.000 z'
        )
    )

    # Concave-concave.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_right(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_right(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.561,0.000 L-1.441,0.000 '
            'A 31.394,31.394 0 0 0 0.000,-3.400 '
            'A 31.394,31.394 0 0 0 1.441,0.000 '
            'L2.561,0.000 '
            'A 30.394,30.394 0 0 1 0.000,-6.923 '
            'A 30.394,30.394 0 0 1 -2.561,0.000 z'
        )
    )

    # Convex-concave.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_left(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_right(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.522,0.000 L-1.477,0.000 '
            'A 30.394,30.394 0 0 1 -0.090,-3.656 '
            'A 31.394,31.394 0 0 0 1.441,0.000 '
            'L2.561,0.000 '
            'A 30.394,30.394 0 0 1 0.144,-6.339 '
            'A 31.394,31.394 0 0 0 -2.522,0.000 z'
        )
    )

    # Concave-convex.
    p = Pen()
    p.stroke_mode(1.0)

    p.move_to(left)
    p.turn_toward(top)
    p.turn_right(5)
    p.arc_to(top, start_slant=0)
    p.turn_toward(right)
    p.turn_left(5)
    p.arc_to(right, end_slant=0)

    assert_path_data(
        p, 3,
        (
            'M-2.561,0.000 L-1.441,0.000 '
            'A 31.394,31.394 0 0 0 0.090,-3.656 '
            'A 30.394,30.394 0 0 1 1.477,0.000 '
            'L2.522,0.000 '
            'A 31.394,31.394 0 0 0 -0.144,-6.339 '
            'A 30.394,30.394 0 0 1 -2.561,0.000 z'
        )
    )