A step in a pressed panel is blended with an S-curve made of two arcs. Set up coordinates with the left-hand end of the lower face at the origin P; the lower face runs from P along the positive x-direction to Q and is 37 mm long. The upper face runs parallel to it 19.7 mm above, from S (directly above P) to R (directly above Q). The first arc, radius 12.7 mm and centred at C1, runs smoothly out of the lower face, leaving it at T1 which is 8 mm along from P. The second arc, radius 7.1 mm and centred at C2, runs smoothly into the upper face at T2. The two arcs meet each other at J, and the curve is smooth there too - there is no kink where one arc becomes the other. The S-curve runs left to right, climbing from the lower face to the upper one.

"""Ogee (S-curve) blend between two parallel faces

Oracle formalization for cadh_t4_cadh_ogee_blend_0022. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(53)

P, Q, S, R, C1, C2, T1, T2, J = scene.add.points(["P", "Q", "S", "R", "C1", "C2", "T1", "T2", "J"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the left-hand end of the lower face (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the left-hand end of the lower face (y)")
scene.constraint.eq(Q.y, 0, description="datum: the lower face PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the part extends in the +x direction")
scene.constraint.eq(P.distance(Q), 37, description="the lower face is 37 long")
scene.constraint.eq(S.y - P.y, 19.7, description="the upper face is 19.7 above the lower one")
scene.constraint.eq(R.y - Q.y, 19.7, description="the upper face is parallel to the lower one")
scene.constraint.eq(S.x, P.x, description="the upper face starts directly above P")
scene.constraint.eq(R.x, Q.x, description="the upper face ends directly above Q")
lower = scene.add.line_segment(P, Q)
upper = scene.add.line_segment(S, R)
arc1 = scene.add.circle(C1)
arc2 = scene.add.circle(C2)
scene.constraint.eq(arc1.radius, 12.7, description="the first blend arc has radius 12.7")
scene.constraint.eq(arc2.radius, 7.1, description="the second blend arc has radius 7.1")
scene.relate.tangent_to_circle(lower, arc1, T1)
scene.relate.tangent_to_circle(upper, arc2, T2)
scene.relate.point_lies_on(J, arc1)
scene.relate.point_lies_on(J, arc2)
scene.relate.point_lies_on(J, scene.add.line_segment(C1, C2))
scene.constraint.eq(T1.x, 8, description="the S-curve leaves the lower face 8 along from P")
scene.constraint.gt(C1.y, 0.05, description="the first arc curves up away from the lower face")
scene.constraint.gt(T2.x - T1.x, 0.05, description="the S-curve runs left to right, from the lower face up to the upper one")


A step in a pressed panel is blended with an S-curve made of two arcs. Set up coordinates with the left-hand end of the lower face at the origin P; the lower face runs from P along the positive x-direction to Q and is 41.3 mm long. The upper face runs parallel to it 17.7 mm above, from S (directly above P) to R (directly above Q). The first arc, radius 12.9 mm and centred at C1, runs smoothly out of the lower face, leaving it at T1 which is 11.9 mm along from P. The second arc, radius 13.6 mm and centred at C2, runs smoothly into the upper face at T2. The two arcs meet each other at J, and the curve is smooth there too - there is no kink where one arc becomes the other. The S-curve runs left to right, climbing from the lower face to the upper one.

Report every point as [x, y] in the datum frame described in the text, and every circle as {centre_label: radius}. Give at least 4 decimal places: a stated fact counts as satisfied only when its residual is below 5e-3 mm.

"""Ogee (S-curve) blend between two parallel faces

Oracle formalization for cadh_t4_cadh_ogee_blend_0023. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(59)

P, Q, S, R, C1, C2, T1, T2, J = scene.add.points(["P", "Q", "S", "R", "C1", "C2", "T1", "T2", "J"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the left-hand end of the lower face (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the left-hand end of the lower face (y)")
scene.constraint.eq(Q.y, 0, description="datum: the lower face PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the part extends in the +x direction")
scene.constraint.eq(P.distance(Q), 41.3, description="the lower face is 41.3 long")
scene.constraint.eq(S.y - P.y, 17.7, description="the upper face is 17.7 above the lower one")
scene.constraint.eq(R.y - Q.y, 17.7, description="the upper face is parallel to the lower one")
scene.constraint.eq(S.x, P.x, description="the upper face starts directly above P")
scene.constraint.eq(R.x, Q.x, description="the upper face ends directly above Q")
lower = scene.add.line_segment(P, Q)
upper = scene.add.line_segment(S, R)
arc1 = scene.add.circle(C1)
arc2 = scene.add.circle(C2)
scene.constraint.eq(arc1.radius, 12.9, description="the first blend arc has radius 12.9")
scene.constraint.eq(arc2.radius, 13.6, description="the second blend arc has radius 13.6")
scene.relate.tangent_to_circle(lower, arc1, T1)
scene.relate.tangent_to_circle(upper, arc2, T2)
scene.relate.point_lies_on(J, arc1)
scene.relate.point_lies_on(J, arc2)
scene.relate.point_lies_on(J, scene.add.line_segment(C1, C2))
scene.constraint.eq(T1.x, 11.9, description="the S-curve leaves the lower face 11.9 along from P")
scene.constraint.gt(C1.y, 0.05, description="the first arc curves up away from the lower face")
scene.constraint.gt(T2.x - T1.x, 0.05, description="the S-curve runs left to right, from the lower face up to the upper one")

'runs smoothly out of' a straight face means the arc is tangent to it, so its centre sits one radius away, square to the face

'no kink where one arc becomes the other' means the two arcs are tangent to EACH OTHER at J

two arcs tangent to each other with the curve bending opposite ways have centre distance equal to the SUM of the radii, with J on the line joining the centres

that fixes how far along the second arc must sit - it is not a free choice

the first arc curves upward away from the lower face, and the curve runs left to right


A step in a pressed panel is blended with an S-curve made of two arcs. Set up coordinates with the left-hand end of the lower face at the origin P; the lower face runs from P along the positive x-direction to Q and is 35.3 mm long. The upper face runs parallel to it 12.9 mm above, from S (directly above P) to R (directly above Q). The first arc, radius 8.2 mm and centred at C1, runs smoothly out of the lower face, leaving it at T1 which is 11.2 mm along from P. The second arc, radius 7.1 mm and centred at C2, runs smoothly into the upper face at T2. The two arcs meet each other at J, and the curve is smooth there too - there is no kink where one arc becomes the other. The S-curve runs left to right, climbing from the lower face to the upper one.

"""Ogee (S-curve) blend between two parallel faces

Oracle formalization for cadh_t4_cadh_ogee_blend_0024. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(51)

P, Q, S, R, C1, C2, T1, T2, J = scene.add.points(["P", "Q", "S", "R", "C1", "C2", "T1", "T2", "J"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the left-hand end of the lower face (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the left-hand end of the lower face (y)")
scene.constraint.eq(Q.y, 0, description="datum: the lower face PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the part extends in the +x direction")
scene.constraint.eq(P.distance(Q), 35.3, description="the lower face is 35.3 long")
scene.constraint.eq(S.y - P.y, 12.9, description="the upper face is 12.9 above the lower one")
scene.constraint.eq(R.y - Q.y, 12.9, description="the upper face is parallel to the lower one")
scene.constraint.eq(S.x, P.x, description="the upper face starts directly above P")
scene.constraint.eq(R.x, Q.x, description="the upper face ends directly above Q")
lower = scene.add.line_segment(P, Q)
upper = scene.add.line_segment(S, R)
arc1 = scene.add.circle(C1)
arc2 = scene.add.circle(C2)
scene.constraint.eq(arc1.radius, 8.2, description="the first blend arc has radius 8.2")
scene.constraint.eq(arc2.radius, 7.1, description="the second blend arc has radius 7.1")
scene.relate.tangent_to_circle(lower, arc1, T1)
scene.relate.tangent_to_circle(upper, arc2, T2)
scene.relate.point_lies_on(J, arc1)
scene.relate.point_lies_on(J, arc2)
scene.relate.point_lies_on(J, scene.add.line_segment(C1, C2))
scene.constraint.eq(T1.x, 11.2, description="the S-curve leaves the lower face 11.2 along from P")
scene.constraint.gt(C1.y, 0.05, description="the first arc curves up away from the lower face")
scene.constraint.gt(T2.x - T1.x, 0.05, description="the S-curve runs left to right, from the lower face up to the upper one")


A step in a pressed panel is blended with an S-curve made of two arcs. Set up coordinates with the left-hand end of the lower face at the origin P; the lower face runs from P along the positive x-direction to Q and is 39.6 mm long. The upper face runs parallel to it 18.3 mm above, from S (directly above P) to R (directly above Q). The first arc, radius 13.1 mm and centred at C1, runs smoothly out of the lower face, leaving it at T1 which is 8.7 mm along from P. The second arc, radius 6.1 mm and centred at C2, runs smoothly into the upper face at T2. The two arcs meet each other at J, and the curve is smooth there too - there is no kink where one arc becomes the other. The S-curve runs left to right, climbing from the lower face to the upper one.

"""Ogee (S-curve) blend between two parallel faces

Oracle formalization for cadh_t4_cadh_ogee_blend_0025. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(56)

P, Q, S, R, C1, C2, T1, T2, J = scene.add.points(["P", "Q", "S", "R", "C1", "C2", "T1", "T2", "J"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the left-hand end of the lower face (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the left-hand end of the lower face (y)")
scene.constraint.eq(Q.y, 0, description="datum: the lower face PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the part extends in the +x direction")
scene.constraint.eq(P.distance(Q), 39.6, description="the lower face is 39.6 long")
scene.constraint.eq(S.y - P.y, 18.3, description="the upper face is 18.3 above the lower one")
scene.constraint.eq(R.y - Q.y, 18.3, description="the upper face is parallel to the lower one")
scene.constraint.eq(S.x, P.x, description="the upper face starts directly above P")
scene.constraint.eq(R.x, Q.x, description="the upper face ends directly above Q")
lower = scene.add.line_segment(P, Q)
upper = scene.add.line_segment(S, R)
arc1 = scene.add.circle(C1)
arc2 = scene.add.circle(C2)
scene.constraint.eq(arc1.radius, 13.1, description="the first blend arc has radius 13.1")
scene.constraint.eq(arc2.radius, 6.1, description="the second blend arc has radius 6.1")
scene.relate.tangent_to_circle(lower, arc1, T1)
scene.relate.tangent_to_circle(upper, arc2, T2)
scene.relate.point_lies_on(J, arc1)
scene.relate.point_lies_on(J, arc2)
scene.relate.point_lies_on(J, scene.add.line_segment(C1, C2))
scene.constraint.eq(T1.x, 8.7, description="the S-curve leaves the lower face 8.7 along from P")
scene.constraint.gt(C1.y, 0.05, description="the first arc curves up away from the lower face")
scene.constraint.gt(T2.x - T1.x, 0.05, description="the S-curve runs left to right, from the lower face up to the upper one")


A flange is drilled with 6 bolt holes spaced evenly around a bolt circle, but the drawing gives the hole spacing rather than the bolt circle itself. Set up coordinates with the flange centre at the origin O and the first hole centre H1 on the positive x-axis; the hole centres are numbered going anticlockwise. Measured in a straight line from one hole centre across to the next one round, the spacing is 11.5 mm. Give the centres of the first 4 holes, and the radius of the bolt circle they sit on.

"""Bolt circle recovered from the hole spacing

Oracle formalization for cadh_t4_cadh_pitch_from_chord_0071. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(20)

O, H1, H2, H3, H4 = scene.add.points(["O", "H1", "H2", "H3", "H4"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the flange centre (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the flange centre (y)")
scene.constraint.eq(H1.y, 0, description="datum: the first hole centre H1 lies on the positive x-axis")
scene.constraint.gt(H1.x, 1.0, description="datum: H1 is on the POSITIVE x side of the centre")
bolt_circle = scene.add.circle(O)
scene.constraint.eq(H1.distance(H2), 11.5, description="the straight distance from one hole centre to the next is 11.5")
scene.relate.point_lies_on(H1, bolt_circle)
scene.relate.point_lies_on(H2, bolt_circle)
scene.relate.point_lies_on(H3, bolt_circle)
scene.relate.point_lies_on(H4, bolt_circle)
scene.constraint.eq(scene.add.angle(H1, O, H2).value, 60, description="the 6 holes are evenly spaced, so H1 and H2 are adjacent")
scene.constraint.gt(cross(O, H1, H2), 0.05, description="the holes are numbered anticlockwise, so H2 follows H1")
scene.constraint.eq(scene.add.angle(H2, O, H3).value, 60, description="the 6 holes are evenly spaced, so H2 and H3 are adjacent")
scene.constraint.gt(cross(O, H2, H3), 0.05, description="the holes are numbered anticlockwise, so H3 follows H2")
scene.constraint.eq(scene.add.angle(H3, O, H4).value, 60, description="the 6 holes are evenly spaced, so H3 and H4 are adjacent")
scene.constraint.gt(cross(O, H3, H4), 0.05, description="the holes are numbered anticlockwise, so H4 follows H3")

the bolt circle size is NOT given - it must be recovered from the hole-to-hole spacing

evenly spaced means adjacent hole centres subtend 60 degrees at the centre

the straight distance between adjacent holes is a CHORD of the bolt circle, not an arc

so the radius is the spacing divided by twice the sine of half that angle

the holes are numbered anticlockwise, which fixes the sense of rotation


A flange is drilled with 6 bolt holes spaced evenly around a bolt circle, but the drawing gives the hole spacing rather than the bolt circle itself. Set up coordinates with the flange centre at the origin O and the first hole centre H1 on the positive x-axis; the hole centres are numbered going anticlockwise. Measured in a straight line from one hole centre across to the next one round, the spacing is 12.3 mm. Give the centres of the first 4 holes, and the radius of the bolt circle they sit on.

"""Bolt circle recovered from the hole spacing

Oracle formalization for cadh_t4_cadh_pitch_from_chord_0072. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(21)

O, H1, H2, H3, H4 = scene.add.points(["O", "H1", "H2", "H3", "H4"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the flange centre (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the flange centre (y)")
scene.constraint.eq(H1.y, 0, description="datum: the first hole centre H1 lies on the positive x-axis")
scene.constraint.gt(H1.x, 1.0, description="datum: H1 is on the POSITIVE x side of the centre")
bolt_circle = scene.add.circle(O)
scene.constraint.eq(H1.distance(H2), 12.3, description="the straight distance from one hole centre to the next is 12.3")
scene.relate.point_lies_on(H1, bolt_circle)
scene.relate.point_lies_on(H2, bolt_circle)
scene.relate.point_lies_on(H3, bolt_circle)
scene.relate.point_lies_on(H4, bolt_circle)
scene.constraint.eq(scene.add.angle(H1, O, H2).value, 60, description="the 6 holes are evenly spaced, so H1 and H2 are adjacent")
scene.constraint.gt(cross(O, H1, H2), 0.05, description="the holes are numbered anticlockwise, so H2 follows H1")
scene.constraint.eq(scene.add.angle(H2, O, H3).value, 60, description="the 6 holes are evenly spaced, so H2 and H3 are adjacent")
scene.constraint.gt(cross(O, H2, H3), 0.05, description="the holes are numbered anticlockwise, so H3 follows H2")
scene.constraint.eq(scene.add.angle(H3, O, H4).value, 60, description="the 6 holes are evenly spaced, so H3 and H4 are adjacent")
scene.constraint.gt(cross(O, H3, H4), 0.05, description="the holes are numbered anticlockwise, so H4 follows H3")


A flange is drilled with 6 bolt holes spaced evenly around a bolt circle, but the drawing gives the hole spacing rather than the bolt circle itself. Set up coordinates with the flange centre at the origin O and the first hole centre H1 on the positive x-axis; the hole centres are numbered going anticlockwise. Measured in a straight line from one hole centre across to the next one round, the spacing is 9.6 mm. Give the centres of the first 4 holes, and the radius of the bolt circle they sit on.

"""Bolt circle recovered from the hole spacing

Oracle formalization for cadh_t4_cadh_pitch_from_chord_0073. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(17)

O, H1, H2, H3, H4 = scene.add.points(["O", "H1", "H2", "H3", "H4"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the flange centre (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the flange centre (y)")
scene.constraint.eq(H1.y, 0, description="datum: the first hole centre H1 lies on the positive x-axis")
scene.constraint.gt(H1.x, 1.0, description="datum: H1 is on the POSITIVE x side of the centre")
bolt_circle = scene.add.circle(O)
scene.constraint.eq(H1.distance(H2), 9.6, description="the straight distance from one hole centre to the next is 9.6")
scene.relate.point_lies_on(H1, bolt_circle)
scene.relate.point_lies_on(H2, bolt_circle)
scene.relate.point_lies_on(H3, bolt_circle)
scene.relate.point_lies_on(H4, bolt_circle)
scene.constraint.eq(scene.add.angle(H1, O, H2).value, 60, description="the 6 holes are evenly spaced, so H1 and H2 are adjacent")
scene.constraint.gt(cross(O, H1, H2), 0.05, description="the holes are numbered anticlockwise, so H2 follows H1")
scene.constraint.eq(scene.add.angle(H2, O, H3).value, 60, description="the 6 holes are evenly spaced, so H2 and H3 are adjacent")
scene.constraint.gt(cross(O, H2, H3), 0.05, description="the holes are numbered anticlockwise, so H3 follows H2")
scene.constraint.eq(scene.add.angle(H3, O, H4).value, 60, description="the 6 holes are evenly spaced, so H3 and H4 are adjacent")
scene.constraint.gt(cross(O, H3, H4), 0.05, description="the holes are numbered anticlockwise, so H4 follows H3")


A flange is drilled with 5 bolt holes spaced evenly around a bolt circle, but the drawing gives the hole spacing rather than the bolt circle itself. Set up coordinates with the flange centre at the origin O and the first hole centre H1 on the positive x-axis; the hole centres are numbered going anticlockwise. Measured in a straight line from one hole centre across to the next one round, the spacing is 15.3 mm. Give the centres of the first 4 holes, and the radius of the bolt circle they sit on.

"""Bolt circle recovered from the hole spacing

Oracle formalization for cadh_t4_cadh_pitch_from_chord_0074. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(22)

O, H1, H2, H3, H4 = scene.add.points(["O", "H1", "H2", "H3", "H4"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the flange centre (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the flange centre (y)")
scene.constraint.eq(H1.y, 0, description="datum: the first hole centre H1 lies on the positive x-axis")
scene.constraint.gt(H1.x, 1.0, description="datum: H1 is on the POSITIVE x side of the centre")
bolt_circle = scene.add.circle(O)
scene.constraint.eq(H1.distance(H2), 15.3, description="the straight distance from one hole centre to the next is 15.3")
scene.relate.point_lies_on(H1, bolt_circle)
scene.relate.point_lies_on(H2, bolt_circle)
scene.relate.point_lies_on(H3, bolt_circle)
scene.relate.point_lies_on(H4, bolt_circle)
scene.constraint.eq(scene.add.angle(H1, O, H2).value, 72, description="the 5 holes are evenly spaced, so H1 and H2 are adjacent")
scene.constraint.gt(cross(O, H1, H2), 0.05, description="the holes are numbered anticlockwise, so H2 follows H1")
scene.constraint.eq(scene.add.angle(H2, O, H3).value, 72, description="the 5 holes are evenly spaced, so H2 and H3 are adjacent")
scene.constraint.gt(cross(O, H2, H3), 0.05, description="the holes are numbered anticlockwise, so H3 follows H2")
scene.constraint.eq(scene.add.angle(H3, O, H4).value, 72, description="the 5 holes are evenly spaced, so H3 and H4 are adjacent")
scene.constraint.gt(cross(O, H3, H4), 0.05, description="the holes are numbered anticlockwise, so H4 follows H3")

evenly spaced means adjacent hole centres subtend 72 degrees at the centre


A flange is drilled with 6 bolt holes spaced evenly around a bolt circle, but the drawing gives the hole spacing rather than the bolt circle itself. Set up coordinates with the flange centre at the origin O and the first hole centre H1 on the positive x-axis; the hole centres are numbered going anticlockwise. Measured in a straight line from one hole centre across to the next one round, the spacing is 10.6 mm. Give the centres of the first 4 holes, and the radius of the bolt circle they sit on.

"""Bolt circle recovered from the hole spacing

Oracle formalization for cadh_t4_cadh_pitch_from_chord_0075. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(19)

O, H1, H2, H3, H4 = scene.add.points(["O", "H1", "H2", "H3", "H4"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the flange centre (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the flange centre (y)")
scene.constraint.eq(H1.y, 0, description="datum: the first hole centre H1 lies on the positive x-axis")
scene.constraint.gt(H1.x, 1.0, description="datum: H1 is on the POSITIVE x side of the centre")
bolt_circle = scene.add.circle(O)
scene.constraint.eq(H1.distance(H2), 10.6, description="the straight distance from one hole centre to the next is 10.6")
scene.relate.point_lies_on(H1, bolt_circle)
scene.relate.point_lies_on(H2, bolt_circle)
scene.relate.point_lies_on(H3, bolt_circle)
scene.relate.point_lies_on(H4, bolt_circle)
scene.constraint.eq(scene.add.angle(H1, O, H2).value, 60, description="the 6 holes are evenly spaced, so H1 and H2 are adjacent")
scene.constraint.gt(cross(O, H1, H2), 0.05, description="the holes are numbered anticlockwise, so H2 follows H1")
scene.constraint.eq(scene.add.angle(H2, O, H3).value, 60, description="the 6 holes are evenly spaced, so H2 and H3 are adjacent")
scene.constraint.gt(cross(O, H2, H3), 0.05, description="the holes are numbered anticlockwise, so H3 follows H2")
scene.constraint.eq(scene.add.angle(H3, O, H4).value, 60, description="the 6 holes are evenly spaced, so H3 and H4 are adjacent")
scene.constraint.gt(cross(O, H3, H4), 0.05, description="the holes are numbered anticlockwise, so H4 follows H3")


A cover plate measures 45.1 mm by 30.9 mm. Set up coordinates with the bottom-left corner at the origin P, the 45.1 mm edge running from P along the positive x-direction to Q, and the 30.9 mm edge running from P along the positive y-direction to S; R is the remaining corner. A hole 8.9 mm across is already drilled with its centre N at 35 mm from edge PS and 13.2 mm from edge PQ. A slot 8.7 mm wide with a rounded end is machined along the line 11.6 mm up from edge PQ, approaching the hole from the left. The slot is extended towards the hole until its rounded end just touches the hole - the two exactly meet, with no material left between them and no overlap. C is the centre of the slot's rounded end.

"""Slot extended until it just touches a fixed hole

Oracle formalization for cadh_t4_cadh_slot_touch_hole_0081. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(64)

P, Q, R, S, C, N = scene.add.points(["P", "Q", "R", "S", "C", "N"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the datum corner of the plate (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the datum corner of the plate (y)")
scene.constraint.eq(Q.y, 0, description="datum: edge PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the plate lies in the +x direction from P")
scene.constraint.eq(P.distance(Q), 45.1, description="plate is 45.1 long along PQ")
scene.constraint.eq(P.distance(S), 30.9, description="plate is 30.9 wide along PS")
scene.relate.perpendicular(scene.add.line_segment(P, Q), scene.add.line_segment(P, S))
scene.constraint.gt(S.y, 1.0, description="datum: the plate lies in the +y direction from P")
scene.constraint.eq(R.x, Q.x + S.x - P.x, description="plate corner R closes the rectangle (x)")
scene.constraint.eq(R.y, Q.y + S.y - P.y, description="plate corner R closes the rectangle (y)")
slot_end = scene.add.circle(C)
scene.constraint.eq(2 * slot_end.radius, 8.7, description="the slot is 8.7 wide, so its rounded end spans that width")
scene.constraint.eq(C.y, 11.6, description="the slot runs along the line 11.6 up from edge PQ")
scene.constraint.eq(N.x, 35, description="the fixed hole centre is 35 from edge PS")
scene.constraint.eq(N.y, 13.2, description="the fixed hole centre is 13.2 from edge PQ")
scene.constraint.eq(C.distance(N), slot_end.radius + 4.45, description="the slot is extended until its rounded end just touches the hole, with no material left between them")
scene.constraint.lt(C.x - N.x, -0.05, description="the slot approaches the hole from the left, so its end centre is to the left of the hole")

the slot end radius is half the stated slot width, and the hole radius is half its across-size

'just touches, no material left and no overlap' means the two circles are externally tangent

externally tangent circles have their centre distance equal to the SUM of the two radii

the slot centreline height and that centre distance together fix how far along the slot end sits

the slot comes in from the left, so its end centre is on the left of the hole, not past it


A cover plate measures 44.2 mm by 30.9 mm. Set up coordinates with the bottom-left corner at the origin P, the 44.2 mm edge running from P along the positive x-direction to Q, and the 30.9 mm edge running from P along the positive y-direction to S; R is the remaining corner. A hole 6.2 mm across is already drilled with its centre N at 31.6 mm from edge PS and 10.5 mm from edge PQ. A slot 8.7 mm wide with a rounded end is machined along the line 14.1 mm up from edge PQ, approaching the hole from the left. The slot is extended towards the hole until its rounded end just touches the hole - the two exactly meet, with no material left between them and no overlap. C is the centre of the slot's rounded end.

"""Slot extended until it just touches a fixed hole

Oracle formalization for cadh_t4_cadh_slot_touch_hole_0082. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(62)

P, Q, R, S, C, N = scene.add.points(["P", "Q", "R", "S", "C", "N"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the datum corner of the plate (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the datum corner of the plate (y)")
scene.constraint.eq(Q.y, 0, description="datum: edge PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the plate lies in the +x direction from P")
scene.constraint.eq(P.distance(Q), 44.2, description="plate is 44.2 long along PQ")
scene.constraint.eq(P.distance(S), 30.9, description="plate is 30.9 wide along PS")
scene.relate.perpendicular(scene.add.line_segment(P, Q), scene.add.line_segment(P, S))
scene.constraint.gt(S.y, 1.0, description="datum: the plate lies in the +y direction from P")
scene.constraint.eq(R.x, Q.x + S.x - P.x, description="plate corner R closes the rectangle (x)")
scene.constraint.eq(R.y, Q.y + S.y - P.y, description="plate corner R closes the rectangle (y)")
slot_end = scene.add.circle(C)
scene.constraint.eq(2 * slot_end.radius, 8.7, description="the slot is 8.7 wide, so its rounded end spans that width")
scene.constraint.eq(C.y, 14.1, description="the slot runs along the line 14.1 up from edge PQ")
scene.constraint.eq(N.x, 31.6, description="the fixed hole centre is 31.6 from edge PS")
scene.constraint.eq(N.y, 10.5, description="the fixed hole centre is 10.5 from edge PQ")
scene.constraint.eq(C.distance(N), slot_end.radius + 3.1, description="the slot is extended until its rounded end just touches the hole, with no material left between them")
scene.constraint.lt(C.x - N.x, -0.05, description="the slot approaches the hole from the left, so its end centre is to the left of the hole")


A cover plate measures 47.3 mm by 31 mm. Set up coordinates with the bottom-left corner at the origin P, the 47.3 mm edge running from P along the positive x-direction to Q, and the 31 mm edge running from P along the positive y-direction to S; R is the remaining corner. A hole 7.8 mm across is already drilled with its centre N at 35.3 mm from edge PS and 17.7 mm from edge PQ. A slot 9.7 mm wide with a rounded end is machined along the line 12.5 mm up from edge PQ, approaching the hole from the left. The slot is extended towards the hole until its rounded end just touches the hole - the two exactly meet, with no material left between them and no overlap. C is the centre of the slot's rounded end.

"""Slot extended until it just touches a fixed hole

Oracle formalization for cadh_t4_cadh_slot_touch_hole_0083. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(66)

P, Q, R, S, C, N = scene.add.points(["P", "Q", "R", "S", "C", "N"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the datum corner of the plate (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the datum corner of the plate (y)")
scene.constraint.eq(Q.y, 0, description="datum: edge PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the plate lies in the +x direction from P")
scene.constraint.eq(P.distance(Q), 47.3, description="plate is 47.3 long along PQ")
scene.constraint.eq(P.distance(S), 31, description="plate is 31 wide along PS")
scene.relate.perpendicular(scene.add.line_segment(P, Q), scene.add.line_segment(P, S))
scene.constraint.gt(S.y, 1.0, description="datum: the plate lies in the +y direction from P")
scene.constraint.eq(R.x, Q.x + S.x - P.x, description="plate corner R closes the rectangle (x)")
scene.constraint.eq(R.y, Q.y + S.y - P.y, description="plate corner R closes the rectangle (y)")
slot_end = scene.add.circle(C)
scene.constraint.eq(2 * slot_end.radius, 9.7, description="the slot is 9.7 wide, so its rounded end spans that width")
scene.constraint.eq(C.y, 12.5, description="the slot runs along the line 12.5 up from edge PQ")
scene.constraint.eq(N.x, 35.3, description="the fixed hole centre is 35.3 from edge PS")
scene.constraint.eq(N.y, 17.7, description="the fixed hole centre is 17.7 from edge PQ")
scene.constraint.eq(C.distance(N), slot_end.radius + 3.9, description="the slot is extended until its rounded end just touches the hole, with no material left between them")
scene.constraint.lt(C.x - N.x, -0.05, description="the slot approaches the hole from the left, so its end centre is to the left of the hole")


A cover plate measures 38.9 mm by 24.3 mm. Set up coordinates with the bottom-left corner at the origin P, the 38.9 mm edge running from P along the positive x-direction to Q, and the 24.3 mm edge running from P along the positive y-direction to S; R is the remaining corner. A hole 7.9 mm across is already drilled with its centre N at 31.1 mm from edge PS and 13.2 mm from edge PQ. A slot 7.3 mm wide with a rounded end is machined along the line 11.7 mm up from edge PQ, approaching the hole from the left. The slot is extended towards the hole until its rounded end just touches the hole - the two exactly meet, with no material left between them and no overlap. C is the centre of the slot's rounded end.

"""Slot extended until it just touches a fixed hole

Oracle formalization for cadh_t4_cadh_slot_touch_hole_0084. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(56)

P, Q, R, S, C, N = scene.add.points(["P", "Q", "R", "S", "C", "N"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the datum corner of the plate (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the datum corner of the plate (y)")
scene.constraint.eq(Q.y, 0, description="datum: edge PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the plate lies in the +x direction from P")
scene.constraint.eq(P.distance(Q), 38.9, description="plate is 38.9 long along PQ")
scene.constraint.eq(P.distance(S), 24.3, description="plate is 24.3 wide along PS")
scene.relate.perpendicular(scene.add.line_segment(P, Q), scene.add.line_segment(P, S))
scene.constraint.gt(S.y, 1.0, description="datum: the plate lies in the +y direction from P")
scene.constraint.eq(R.x, Q.x + S.x - P.x, description="plate corner R closes the rectangle (x)")
scene.constraint.eq(R.y, Q.y + S.y - P.y, description="plate corner R closes the rectangle (y)")
slot_end = scene.add.circle(C)
scene.constraint.eq(2 * slot_end.radius, 7.3, description="the slot is 7.3 wide, so its rounded end spans that width")
scene.constraint.eq(C.y, 11.7, description="the slot runs along the line 11.7 up from edge PQ")
scene.constraint.eq(N.x, 31.1, description="the fixed hole centre is 31.1 from edge PS")
scene.constraint.eq(N.y, 13.2, description="the fixed hole centre is 13.2 from edge PQ")
scene.constraint.eq(C.distance(N), slot_end.radius + 3.95, description="the slot is extended until its rounded end just touches the hole, with no material left between them")
scene.constraint.lt(C.x - N.x, -0.05, description="the slot approaches the hole from the left, so its end centre is to the left of the hole")


A cover plate measures 43.5 mm by 27.6 mm. Set up coordinates with the bottom-left corner at the origin P, the 43.5 mm edge running from P along the positive x-direction to Q, and the 27.6 mm edge running from P along the positive y-direction to S; R is the remaining corner. A hole 8.7 mm across is already drilled with its centre N at 34.7 mm from edge PS and 14.2 mm from edge PQ. A slot 7.9 mm wide with a rounded end is machined along the line 15.1 mm up from edge PQ, approaching the hole from the left. The slot is extended towards the hole until its rounded end just touches the hole - the two exactly meet, with no material left between them and no overlap. C is the centre of the slot's rounded end.

"""Slot extended until it just touches a fixed hole

Oracle formalization for cadh_t4_cadh_slot_touch_hole_0085. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(62)

P, Q, R, S, C, N = scene.add.points(["P", "Q", "R", "S", "C", "N"])

scene.constraint.eq(P.x, 0, description="datum: P is the origin, the datum corner of the plate (x)")
scene.constraint.eq(P.y, 0, description="datum: P is the origin, the datum corner of the plate (y)")
scene.constraint.eq(Q.y, 0, description="datum: edge PQ runs along the x-axis")
scene.constraint.gt(Q.x, 1.0, description="datum: the plate lies in the +x direction from P")
scene.constraint.eq(P.distance(Q), 43.5, description="plate is 43.5 long along PQ")
scene.constraint.eq(P.distance(S), 27.6, description="plate is 27.6 wide along PS")
scene.relate.perpendicular(scene.add.line_segment(P, Q), scene.add.line_segment(P, S))
scene.constraint.gt(S.y, 1.0, description="datum: the plate lies in the +y direction from P")
scene.constraint.eq(R.x, Q.x + S.x - P.x, description="plate corner R closes the rectangle (x)")
scene.constraint.eq(R.y, Q.y + S.y - P.y, description="plate corner R closes the rectangle (y)")
slot_end = scene.add.circle(C)
scene.constraint.eq(2 * slot_end.radius, 7.9, description="the slot is 7.9 wide, so its rounded end spans that width")
scene.constraint.eq(C.y, 15.1, description="the slot runs along the line 15.1 up from edge PQ")
scene.constraint.eq(N.x, 34.7, description="the fixed hole centre is 34.7 from edge PS")
scene.constraint.eq(N.y, 14.2, description="the fixed hole centre is 14.2 from edge PQ")
scene.constraint.eq(C.distance(N), slot_end.radius + 4.35, description="the slot is extended until its rounded end just touches the hole, with no material left between them")
scene.constraint.lt(C.x - N.x, -0.05, description="the slot approaches the hole from the left, so its end centre is to the left of the hole")


A bore is to be positioned relative to a corner of a casting by scribing tangent lines. Set up coordinates with the centre of the bore at the origin O, and the corner E on the positive x-axis from it. The bore is 14.6 mm across. Two straight lines are scribed from the corner E so that each one just grazes the bore, touching it at a single point - T1 above the line OE and T2 below it. Measured from the corner along either scribed line to the point where it meets the bore, the distance is 17.8 mm. Work out how far the corner has to be from the bore centre.

"""Corner standoff from a scribed tangent length

Oracle formalization for cadh_t4_cadh_tangent_from_corner_0091. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(30)

O, E, T1, T2 = scene.add.points(["O", "E", "T1", "T2"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the centre of the bore (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the centre of the bore (y)")
scene.constraint.eq(E.y, 0, description="datum: the corner E lies on the positive x-axis from O")
scene.constraint.gt(E.x, 1.0, description="datum: E is on the POSITIVE x side of the bore centre")
bore = scene.add.circle(O)
scene.constraint.eq(2 * bore.radius, 14.6, description="the bore is 14.6 across")
scene.relate.point_lies_on(T1, bore)
scene.relate.point_lies_on(T2, bore)
scene.relate.perpendicular(scene.add.line_segment(O, T1), scene.add.line_segment(E, T1))
scene.relate.perpendicular(scene.add.line_segment(O, T2), scene.add.line_segment(E, T2))
scene.constraint.eq(E.distance(T1), 17.8, description="the straight scribed line from the corner to where it meets the bore measures 17.8")
scene.constraint.gt(T1.y, 0.05, description="T1 is the upper of the two touch points")
scene.constraint.lt(T2.y, -0.05, description="T2 is the lower of the two touch points")

the standoff distance is NOT given - it must be recovered from the scribed length

a line that 'just grazes' the bore is tangent to it, so the radius to the touch point is square to that line

that makes O, T1 and E a right-angled triangle with the right angle at T1

so the centre-to-corner distance is the square root of (scribed length squared plus radius squared)

T1 is the upper touch point and T2 the lower one


A bore is to be positioned relative to a corner of a casting by scribing tangent lines. Set up coordinates with the centre of the bore at the origin O, and the corner E on the positive x-axis from it. The bore is 16.1 mm across. Two straight lines are scribed from the corner E so that each one just grazes the bore, touching it at a single point - T1 above the line OE and T2 below it. Measured from the corner along either scribed line to the point where it meets the bore, the distance is 15.3 mm. Work out how far the corner has to be from the bore centre.

"""Corner standoff from a scribed tangent length

Oracle formalization for cadh_t4_cadh_tangent_from_corner_0092. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(27)

O, E, T1, T2 = scene.add.points(["O", "E", "T1", "T2"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the centre of the bore (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the centre of the bore (y)")
scene.constraint.eq(E.y, 0, description="datum: the corner E lies on the positive x-axis from O")
scene.constraint.gt(E.x, 1.0, description="datum: E is on the POSITIVE x side of the bore centre")
bore = scene.add.circle(O)
scene.constraint.eq(2 * bore.radius, 16.1, description="the bore is 16.1 across")
scene.relate.point_lies_on(T1, bore)
scene.relate.point_lies_on(T2, bore)
scene.relate.perpendicular(scene.add.line_segment(O, T1), scene.add.line_segment(E, T1))
scene.relate.perpendicular(scene.add.line_segment(O, T2), scene.add.line_segment(E, T2))
scene.constraint.eq(E.distance(T1), 15.3, description="the straight scribed line from the corner to where it meets the bore measures 15.3")
scene.constraint.gt(T1.y, 0.05, description="T1 is the upper of the two touch points")
scene.constraint.lt(T2.y, -0.05, description="T2 is the lower of the two touch points")


A bore is to be positioned relative to a corner of a casting by scribing tangent lines. Set up coordinates with the centre of the bore at the origin O, and the corner E on the positive x-axis from it. The bore is 20.1 mm across. Two straight lines are scribed from the corner E so that each one just grazes the bore, touching it at a single point - T1 above the line OE and T2 below it. Measured from the corner along either scribed line to the point where it meets the bore, the distance is 25 mm. Work out how far the corner has to be from the bore centre.

"""Corner standoff from a scribed tangent length

Oracle formalization for cadh_t4_cadh_tangent_from_corner_0093. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(40)

O, E, T1, T2 = scene.add.points(["O", "E", "T1", "T2"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the centre of the bore (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the centre of the bore (y)")
scene.constraint.eq(E.y, 0, description="datum: the corner E lies on the positive x-axis from O")
scene.constraint.gt(E.x, 1.0, description="datum: E is on the POSITIVE x side of the bore centre")
bore = scene.add.circle(O)
scene.constraint.eq(2 * bore.radius, 20.1, description="the bore is 20.1 across")
scene.relate.point_lies_on(T1, bore)
scene.relate.point_lies_on(T2, bore)
scene.relate.perpendicular(scene.add.line_segment(O, T1), scene.add.line_segment(E, T1))
scene.relate.perpendicular(scene.add.line_segment(O, T2), scene.add.line_segment(E, T2))
scene.constraint.eq(E.distance(T1), 25, description="the straight scribed line from the corner to where it meets the bore measures 25")
scene.constraint.gt(T1.y, 0.05, description="T1 is the upper of the two touch points")
scene.constraint.lt(T2.y, -0.05, description="T2 is the lower of the two touch points")


A bore is to be positioned relative to a corner of a casting by scribing tangent lines. Set up coordinates with the centre of the bore at the origin O, and the corner E on the positive x-axis from it. The bore is 21.1 mm across. Two straight lines are scribed from the corner E so that each one just grazes the bore, touching it at a single point - T1 above the line OE and T2 below it. Measured from the corner along either scribed line to the point where it meets the bore, the distance is 15.5 mm. Work out how far the corner has to be from the bore centre.

"""Corner standoff from a scribed tangent length

Oracle formalization for cadh_t4_cadh_tangent_from_corner_0094. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(29)

O, E, T1, T2 = scene.add.points(["O", "E", "T1", "T2"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the centre of the bore (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the centre of the bore (y)")
scene.constraint.eq(E.y, 0, description="datum: the corner E lies on the positive x-axis from O")
scene.constraint.gt(E.x, 1.0, description="datum: E is on the POSITIVE x side of the bore centre")
bore = scene.add.circle(O)
scene.constraint.eq(2 * bore.radius, 21.1, description="the bore is 21.1 across")
scene.relate.point_lies_on(T1, bore)
scene.relate.point_lies_on(T2, bore)
scene.relate.perpendicular(scene.add.line_segment(O, T1), scene.add.line_segment(E, T1))
scene.relate.perpendicular(scene.add.line_segment(O, T2), scene.add.line_segment(E, T2))
scene.constraint.eq(E.distance(T1), 15.5, description="the straight scribed line from the corner to where it meets the bore measures 15.5")
scene.constraint.gt(T1.y, 0.05, description="T1 is the upper of the two touch points")
scene.constraint.lt(T2.y, -0.05, description="T2 is the lower of the two touch points")


A bore is to be positioned relative to a corner of a casting by scribing tangent lines. Set up coordinates with the centre of the bore at the origin O, and the corner E on the positive x-axis from it. The bore is 14.1 mm across. Two straight lines are scribed from the corner E so that each one just grazes the bore, touching it at a single point - T1 above the line OE and T2 below it. Measured from the corner along either scribed line to the point where it meets the bore, the distance is 16.3 mm. Work out how far the corner has to be from the bore centre.

"""Corner standoff from a scribed tangent length

Oracle formalization for cadh_t4_cadh_tangent_from_corner_0095. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(28)

O, E, T1, T2 = scene.add.points(["O", "E", "T1", "T2"])

scene.constraint.eq(O.x, 0, description="datum: O is the origin, the centre of the bore (x)")
scene.constraint.eq(O.y, 0, description="datum: O is the origin, the centre of the bore (y)")
scene.constraint.eq(E.y, 0, description="datum: the corner E lies on the positive x-axis from O")
scene.constraint.gt(E.x, 1.0, description="datum: E is on the POSITIVE x side of the bore centre")
bore = scene.add.circle(O)
scene.constraint.eq(2 * bore.radius, 14.1, description="the bore is 14.1 across")
scene.relate.point_lies_on(T1, bore)
scene.relate.point_lies_on(T2, bore)
scene.relate.perpendicular(scene.add.line_segment(O, T1), scene.add.line_segment(E, T1))
scene.relate.perpendicular(scene.add.line_segment(O, T2), scene.add.line_segment(E, T2))
scene.constraint.eq(E.distance(T1), 16.3, description="the straight scribed line from the corner to where it meets the bore measures 16.3")
scene.constraint.gt(T1.y, 0.05, description="T1 is the upper of the two touch points")
scene.constraint.lt(T2.y, -0.05, description="T2 is the lower of the two touch points")


Two pulleys are to be set on a bracket and the centre distance has to be worked out from the belt. Set up coordinates with the centre of the large pulley at the origin C and the centre of the small pulley at D on the positive x-axis. The large pulley is 22.6 mm across and the small one is 9.3 mm across. A straight belt run passes over the tops of both, touching the large one at T and the small one at V, and it does not cross over between them. The straight run of belt between those two touch points measures 35 mm. Work out how far apart the two centres must be.

"""Centre distance from a stated belt run

Oracle formalization for cadh_t4_cadh_tangent_length_inverse_0051. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(52)

C, D, T, V = scene.add.points(["C", "D", "T", "V"])

scene.constraint.eq(C.x, 0, description="datum: C is the origin, the centre of the large pulley (x)")
scene.constraint.eq(C.y, 0, description="datum: C is the origin, the centre of the large pulley (y)")
scene.constraint.eq(D.y, 0, description="datum: the line of centres CD runs along the x-axis")
scene.constraint.gt(D.x, 1.0, description="datum: the small pulley lies in the +x direction")
pulley_C = scene.add.circle(C)
pulley_D = scene.add.circle(D)
scene.constraint.eq(2 * pulley_C.radius, 22.6, description="the large pulley is 22.6 across")
scene.constraint.eq(2 * pulley_D.radius, 9.3, description="the small pulley is 9.3 across")
belt = scene.add.line(T, V)
scene.relate.tangent_to_circle(belt, pulley_C, T)
scene.relate.tangent_to_circle(belt, pulley_D, V)
scene.constraint.eq(T.distance(V), 35, description="the straight run of belt between the two touch points measures 35")
scene.constraint.gt(cross(C, D, T), 0.05, description="the belt run shown passes over the top of both pulleys")
scene.constraint.gt(dot(C, T, D, V), 0.05, description="the belt does not cross over between the pulleys")

the centre distance is NOT given - it has to be recovered from the belt length

each pulley radius is half the stated across-size

for a belt that does not cross over, the straight run, the centre distance and the difference of the radii form a right-angled triangle

so the centre distance is the square root of (belt run squared plus the radius difference squared)

'does not cross over' selects the external tangent, not the crossing one; 'over the tops' picks the upper one


Two pulleys are to be set on a bracket and the centre distance has to be worked out from the belt. Set up coordinates with the centre of the large pulley at the origin C and the centre of the small pulley at D on the positive x-axis. The large pulley is 19.7 mm across and the small one is 7.3 mm across. A straight belt run passes over the tops of both, touching the large one at T and the small one at V, and it does not cross over between them. The straight run of belt between those two touch points measures 29.6 mm. Work out how far apart the two centres must be.

"""Centre distance from a stated belt run

Oracle formalization for cadh_t4_cadh_tangent_length_inverse_0052. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(45)

C, D, T, V = scene.add.points(["C", "D", "T", "V"])

scene.constraint.eq(C.x, 0, description="datum: C is the origin, the centre of the large pulley (x)")
scene.constraint.eq(C.y, 0, description="datum: C is the origin, the centre of the large pulley (y)")
scene.constraint.eq(D.y, 0, description="datum: the line of centres CD runs along the x-axis")
scene.constraint.gt(D.x, 1.0, description="datum: the small pulley lies in the +x direction")
pulley_C = scene.add.circle(C)
pulley_D = scene.add.circle(D)
scene.constraint.eq(2 * pulley_C.radius, 19.7, description="the large pulley is 19.7 across")
scene.constraint.eq(2 * pulley_D.radius, 7.3, description="the small pulley is 7.3 across")
belt = scene.add.line(T, V)
scene.relate.tangent_to_circle(belt, pulley_C, T)
scene.relate.tangent_to_circle(belt, pulley_D, V)
scene.constraint.eq(T.distance(V), 29.6, description="the straight run of belt between the two touch points measures 29.6")
scene.constraint.gt(cross(C, D, T), 0.05, description="the belt run shown passes over the top of both pulleys")
scene.constraint.gt(dot(C, T, D, V), 0.05, description="the belt does not cross over between the pulleys")


Two pulleys are to be set on a bracket and the centre distance has to be worked out from the belt. Set up coordinates with the centre of the large pulley at the origin C and the centre of the small pulley at D on the positive x-axis. The large pulley is 25.5 mm across and the small one is 9.5 mm across. A straight belt run passes over the tops of both, touching the large one at T and the small one at V, and it does not cross over between them. The straight run of belt between those two touch points measures 31.4 mm. Work out how far apart the two centres must be.

"""Centre distance from a stated belt run

Oracle formalization for cadh_t4_cadh_tangent_length_inverse_0053. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(49)

C, D, T, V = scene.add.points(["C", "D", "T", "V"])

scene.constraint.eq(C.x, 0, description="datum: C is the origin, the centre of the large pulley (x)")
scene.constraint.eq(C.y, 0, description="datum: C is the origin, the centre of the large pulley (y)")
scene.constraint.eq(D.y, 0, description="datum: the line of centres CD runs along the x-axis")
scene.constraint.gt(D.x, 1.0, description="datum: the small pulley lies in the +x direction")
pulley_C = scene.add.circle(C)
pulley_D = scene.add.circle(D)
scene.constraint.eq(2 * pulley_C.radius, 25.5, description="the large pulley is 25.5 across")
scene.constraint.eq(2 * pulley_D.radius, 9.5, description="the small pulley is 9.5 across")
belt = scene.add.line(T, V)
scene.relate.tangent_to_circle(belt, pulley_C, T)
scene.relate.tangent_to_circle(belt, pulley_D, V)
scene.constraint.eq(T.distance(V), 31.4, description="the straight run of belt between the two touch points measures 31.4")
scene.constraint.gt(cross(C, D, T), 0.05, description="the belt run shown passes over the top of both pulleys")
scene.constraint.gt(dot(C, T, D, V), 0.05, description="the belt does not cross over between the pulleys")


Two pulleys are to be set on a bracket and the centre distance has to be worked out from the belt. Set up coordinates with the centre of the large pulley at the origin C and the centre of the small pulley at D on the positive x-axis. The large pulley is 20.4 mm across and the small one is 10.7 mm across. A straight belt run passes over the tops of both, touching the large one at T and the small one at V, and it does not cross over between them. The straight run of belt between those two touch points measures 35.1 mm. Work out how far apart the two centres must be.

"""Centre distance from a stated belt run

Oracle formalization for cadh_t4_cadh_tangent_length_inverse_0054. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(52)

C, D, T, V = scene.add.points(["C", "D", "T", "V"])

scene.constraint.eq(C.x, 0, description="datum: C is the origin, the centre of the large pulley (x)")
scene.constraint.eq(C.y, 0, description="datum: C is the origin, the centre of the large pulley (y)")
scene.constraint.eq(D.y, 0, description="datum: the line of centres CD runs along the x-axis")
scene.constraint.gt(D.x, 1.0, description="datum: the small pulley lies in the +x direction")
pulley_C = scene.add.circle(C)
pulley_D = scene.add.circle(D)
scene.constraint.eq(2 * pulley_C.radius, 20.4, description="the large pulley is 20.4 across")
scene.constraint.eq(2 * pulley_D.radius, 10.7, description="the small pulley is 10.7 across")
belt = scene.add.line(T, V)
scene.relate.tangent_to_circle(belt, pulley_C, T)
scene.relate.tangent_to_circle(belt, pulley_D, V)
scene.constraint.eq(T.distance(V), 35.1, description="the straight run of belt between the two touch points measures 35.1")
scene.constraint.gt(cross(C, D, T), 0.05, description="the belt run shown passes over the top of both pulleys")
scene.constraint.gt(dot(C, T, D, V), 0.05, description="the belt does not cross over between the pulleys")


Two pulleys are to be set on a bracket and the centre distance has to be worked out from the belt. Set up coordinates with the centre of the large pulley at the origin C and the centre of the small pulley at D on the positive x-axis. The large pulley is 18.7 mm across and the small one is 8.3 mm across. A straight belt run passes over the tops of both, touching the large one at T and the small one at V, and it does not cross over between them. The straight run of belt between those two touch points measures 29.5 mm. Work out how far apart the two centres must be.

"""Centre distance from a stated belt run

Oracle formalization for cadh_t4_cadh_tangent_length_inverse_0055. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(45)

C, D, T, V = scene.add.points(["C", "D", "T", "V"])

scene.constraint.eq(C.x, 0, description="datum: C is the origin, the centre of the large pulley (x)")
scene.constraint.eq(C.y, 0, description="datum: C is the origin, the centre of the large pulley (y)")
scene.constraint.eq(D.y, 0, description="datum: the line of centres CD runs along the x-axis")
scene.constraint.gt(D.x, 1.0, description="datum: the small pulley lies in the +x direction")
pulley_C = scene.add.circle(C)
pulley_D = scene.add.circle(D)
scene.constraint.eq(2 * pulley_C.radius, 18.7, description="the large pulley is 18.7 across")
scene.constraint.eq(2 * pulley_D.radius, 8.3, description="the small pulley is 8.3 across")
belt = scene.add.line(T, V)
scene.relate.tangent_to_circle(belt, pulley_C, T)
scene.relate.tangent_to_circle(belt, pulley_D, V)
scene.constraint.eq(T.distance(V), 29.5, description="the straight run of belt between the two touch points measures 29.5")
scene.constraint.gt(cross(C, D, T), 0.05, description="the belt run shown passes over the top of both pulleys")
scene.constraint.gt(dot(C, T, D, V), 0.05, description="the belt does not cross over between the pulleys")


Two round bars of different sizes are nested in a vee block, one resting on top of the other, both sitting centrally in the vee. Set up coordinates with the apex of the vee at the origin Z, the vee opening upward and symmetric about the positive y-direction; the right-hand face runs from Z to A and the left-hand face runs from Z to B. Each face is 38 mm long and the included angle of the vee is 55 degrees. The lower bar is 11.5 mm across; its centre is F1 and it touches the right-hand face at T1. The upper bar rests on top of the lower one, touching it, and is itself pushed out until it also touches the vee faces; its centre is F2 and it touches the right-hand face at T2. Work out how big the upper bar has to be.

"""Two bars nested in a vee block

Oracle formalization for cadh_t4_cadh_two_bars_vee_0011. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(49)

Z, A, B, F1, F2, T1, T2 = scene.add.points(["Z", "A", "B", "F1", "F2", "T1", "T2"])

scene.constraint.eq(Z.x, 0, description="datum: Z is the origin, the apex of the vee (x)")
scene.constraint.eq(Z.y, 0, description="datum: Z is the origin, the apex of the vee (y)")
scene.constraint.eq(A.x + B.x, 0, description="datum: the vee is symmetric about the y-axis")
scene.constraint.eq(A.y, B.y, description="datum: the vee is symmetric about the y-axis")
scene.constraint.gt(A.x, 1.0, description="datum: A is the right-hand face end, B the left-hand one")
scene.constraint.eq(Z.distance(A), 38, description="each vee face is 38 long")
scene.constraint.eq(scene.add.angle(A, Z, B).value, 55, description="the included angle of the vee is 55 degrees")
face_r = scene.add.line_segment(Z, A)
bar_low = scene.add.circle(F1)
bar_up = scene.add.circle(F2)
scene.constraint.eq(2 * bar_low.radius, 11.5, description="the lower bar is 11.5 across")
scene.relate.tangent_to_circle(face_r, bar_low, T1)
scene.relate.tangent_to_circle(face_r, bar_up, T2)
scene.constraint.eq(F1.x, Z.x, description="the lower bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F2.x, Z.x, description="the upper bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F1.distance(F2), bar_low.radius + bar_up.radius, description="the two bars touch each other")
scene.constraint.gt(F1.y, 0.05, description="the lower bar sits inside the vee, above the apex")
scene.constraint.gt(F2.y - F1.y, 0.05, description="the upper bar rests on top of the lower one")

the upper bar's size is NOT given - it follows from touching the faces AND the lower bar

a bar sitting centrally and touching both faces has its centre on the vee axis at height radius/sin(half the included angle)

two bars touching each other have their centre distance equal to the SUM of their radii

combining those gives the upper radius as the lower radius times (1+sin a)/(1-sin a)

the upper bar rests ON TOP of the lower one, not below it


Two round bars of different sizes are nested in a vee block, one resting on top of the other, both sitting centrally in the vee. Set up coordinates with the apex of the vee at the origin Z, the vee opening upward and symmetric about the positive y-direction; the right-hand face runs from Z to A and the left-hand face runs from Z to B. Each face is 39.1 mm long and the included angle of the vee is 50 degrees. The lower bar is 11.8 mm across; its centre is F1 and it touches the right-hand face at T1. The upper bar rests on top of the lower one, touching it, and is itself pushed out until it also touches the vee faces; its centre is F2 and it touches the right-hand face at T2. Work out how big the upper bar has to be.

"""Two bars nested in a vee block

Oracle formalization for cadh_t4_cadh_two_bars_vee_0012. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(51)

Z, A, B, F1, F2, T1, T2 = scene.add.points(["Z", "A", "B", "F1", "F2", "T1", "T2"])

scene.constraint.eq(Z.x, 0, description="datum: Z is the origin, the apex of the vee (x)")
scene.constraint.eq(Z.y, 0, description="datum: Z is the origin, the apex of the vee (y)")
scene.constraint.eq(A.x + B.x, 0, description="datum: the vee is symmetric about the y-axis")
scene.constraint.eq(A.y, B.y, description="datum: the vee is symmetric about the y-axis")
scene.constraint.gt(A.x, 1.0, description="datum: A is the right-hand face end, B the left-hand one")
scene.constraint.eq(Z.distance(A), 39.1, description="each vee face is 39.1 long")
scene.constraint.eq(scene.add.angle(A, Z, B).value, 50, description="the included angle of the vee is 50 degrees")
face_r = scene.add.line_segment(Z, A)
bar_low = scene.add.circle(F1)
bar_up = scene.add.circle(F2)
scene.constraint.eq(2 * bar_low.radius, 11.8, description="the lower bar is 11.8 across")
scene.relate.tangent_to_circle(face_r, bar_low, T1)
scene.relate.tangent_to_circle(face_r, bar_up, T2)
scene.constraint.eq(F1.x, Z.x, description="the lower bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F2.x, Z.x, description="the upper bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F1.distance(F2), bar_low.radius + bar_up.radius, description="the two bars touch each other")
scene.constraint.gt(F1.y, 0.05, description="the lower bar sits inside the vee, above the apex")
scene.constraint.gt(F2.y - F1.y, 0.05, description="the upper bar rests on top of the lower one")


Two round bars of different sizes are nested in a vee block, one resting on top of the other, both sitting centrally in the vee. Set up coordinates with the apex of the vee at the origin Z, the vee opening upward and symmetric about the positive y-direction; the right-hand face runs from Z to A and the left-hand face runs from Z to B. Each face is 29 mm long and the included angle of the vee is 55 degrees. The lower bar is 7.3 mm across; its centre is F1 and it touches the right-hand face at T1. The upper bar rests on top of the lower one, touching it, and is itself pushed out until it also touches the vee faces; its centre is F2 and it touches the right-hand face at T2. Work out how big the upper bar has to be.

"""Two bars nested in a vee block

Oracle formalization for cadh_t4_cadh_two_bars_vee_0013. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(38)

Z, A, B, F1, F2, T1, T2 = scene.add.points(["Z", "A", "B", "F1", "F2", "T1", "T2"])

scene.constraint.eq(Z.x, 0, description="datum: Z is the origin, the apex of the vee (x)")
scene.constraint.eq(Z.y, 0, description="datum: Z is the origin, the apex of the vee (y)")
scene.constraint.eq(A.x + B.x, 0, description="datum: the vee is symmetric about the y-axis")
scene.constraint.eq(A.y, B.y, description="datum: the vee is symmetric about the y-axis")
scene.constraint.gt(A.x, 1.0, description="datum: A is the right-hand face end, B the left-hand one")
scene.constraint.eq(Z.distance(A), 29, description="each vee face is 29 long")
scene.constraint.eq(scene.add.angle(A, Z, B).value, 55, description="the included angle of the vee is 55 degrees")
face_r = scene.add.line_segment(Z, A)
bar_low = scene.add.circle(F1)
bar_up = scene.add.circle(F2)
scene.constraint.eq(2 * bar_low.radius, 7.3, description="the lower bar is 7.3 across")
scene.relate.tangent_to_circle(face_r, bar_low, T1)
scene.relate.tangent_to_circle(face_r, bar_up, T2)
scene.constraint.eq(F1.x, Z.x, description="the lower bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F2.x, Z.x, description="the upper bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F1.distance(F2), bar_low.radius + bar_up.radius, description="the two bars touch each other")
scene.constraint.gt(F1.y, 0.05, description="the lower bar sits inside the vee, above the apex")
scene.constraint.gt(F2.y - F1.y, 0.05, description="the upper bar rests on top of the lower one")


Two round bars of different sizes are nested in a vee block, one resting on top of the other, both sitting centrally in the vee. Set up coordinates with the apex of the vee at the origin Z, the vee opening upward and symmetric about the positive y-direction; the right-hand face runs from Z to A and the left-hand face runs from Z to B. Each face is 36.1 mm long and the included angle of the vee is 70 degrees. The lower bar is 8.4 mm across; its centre is F1 and it touches the right-hand face at T1. The upper bar rests on top of the lower one, touching it, and is itself pushed out until it also touches the vee faces; its centre is F2 and it touches the right-hand face at T2. Work out how big the upper bar has to be.

"""Two bars nested in a vee block

Oracle formalization for cadh_t4_cadh_two_bars_vee_0014. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(43)

Z, A, B, F1, F2, T1, T2 = scene.add.points(["Z", "A", "B", "F1", "F2", "T1", "T2"])

scene.constraint.eq(Z.x, 0, description="datum: Z is the origin, the apex of the vee (x)")
scene.constraint.eq(Z.y, 0, description="datum: Z is the origin, the apex of the vee (y)")
scene.constraint.eq(A.x + B.x, 0, description="datum: the vee is symmetric about the y-axis")
scene.constraint.eq(A.y, B.y, description="datum: the vee is symmetric about the y-axis")
scene.constraint.gt(A.x, 1.0, description="datum: A is the right-hand face end, B the left-hand one")
scene.constraint.eq(Z.distance(A), 36.1, description="each vee face is 36.1 long")
scene.constraint.eq(scene.add.angle(A, Z, B).value, 70, description="the included angle of the vee is 70 degrees")
face_r = scene.add.line_segment(Z, A)
bar_low = scene.add.circle(F1)
bar_up = scene.add.circle(F2)
scene.constraint.eq(2 * bar_low.radius, 8.4, description="the lower bar is 8.4 across")
scene.relate.tangent_to_circle(face_r, bar_low, T1)
scene.relate.tangent_to_circle(face_r, bar_up, T2)
scene.constraint.eq(F1.x, Z.x, description="the lower bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F2.x, Z.x, description="the upper bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F1.distance(F2), bar_low.radius + bar_up.radius, description="the two bars touch each other")
scene.constraint.gt(F1.y, 0.05, description="the lower bar sits inside the vee, above the apex")
scene.constraint.gt(F2.y - F1.y, 0.05, description="the upper bar rests on top of the lower one")


Two round bars of different sizes are nested in a vee block, one resting on top of the other, both sitting centrally in the vee. Set up coordinates with the apex of the vee at the origin Z, the vee opening upward and symmetric about the positive y-direction; the right-hand face runs from Z to A and the left-hand face runs from Z to B. Each face is 36.9 mm long and the included angle of the vee is 60 degrees. The lower bar is 7.3 mm across; its centre is F1 and it touches the right-hand face at T1. The upper bar rests on top of the lower one, touching it, and is itself pushed out until it also touches the vee faces; its centre is F2 and it touches the right-hand face at T2. Work out how big the upper bar has to be.

"""Two bars nested in a vee block

Oracle formalization for cadh_t4_cadh_two_bars_vee_0015. Every constraint below corresponds to one
statement in the problem text; the datum constraints fix the coordinate frame
the text describes, and the inequality constraints encode the discrete choices
the text makes explicit (which side, which branch).
"""
from pygeox import GeoScene

def cross(A, B, P):
    """z-component of (B-A) x (P-A). Positive iff P lies to the LEFT of the
    directed line A->B. Used to state 'above', 'on the far side', 'anticlockwise'
    without any appeal to a picture."""
    return (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x)

def dot(A, B, C, D):
    """(B-A) . (D-C). Positive iff the two directions point the same way."""
    return (B.x - A.x) * (D.x - C.x) + (B.y - A.y) * (D.y - C.y)

scene = GeoScene(47)

Z, A, B, F1, F2, T1, T2 = scene.add.points(["Z", "A", "B", "F1", "F2", "T1", "T2"])

scene.constraint.eq(Z.x, 0, description="datum: Z is the origin, the apex of the vee (x)")
scene.constraint.eq(Z.y, 0, description="datum: Z is the origin, the apex of the vee (y)")
scene.constraint.eq(A.x + B.x, 0, description="datum: the vee is symmetric about the y-axis")
scene.constraint.eq(A.y, B.y, description="datum: the vee is symmetric about the y-axis")
scene.constraint.gt(A.x, 1.0, description="datum: A is the right-hand face end, B the left-hand one")
scene.constraint.eq(Z.distance(A), 36.9, description="each vee face is 36.9 long")
scene.constraint.eq(scene.add.angle(A, Z, B).value, 60, description="the included angle of the vee is 60 degrees")
face_r = scene.add.line_segment(Z, A)
bar_low = scene.add.circle(F1)
bar_up = scene.add.circle(F2)
scene.constraint.eq(2 * bar_low.radius, 7.3, description="the lower bar is 7.3 across")
scene.relate.tangent_to_circle(face_r, bar_low, T1)
scene.relate.tangent_to_circle(face_r, bar_up, T2)
scene.constraint.eq(F1.x, Z.x, description="the lower bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F2.x, Z.x, description="the upper bar sits centrally in the vee, on its axis of symmetry")
scene.constraint.eq(F1.distance(F2), bar_low.radius + bar_up.radius, description="the two bars touch each other")
scene.constraint.gt(F1.y, 0.05, description="the lower bar sits inside the vee, above the apex")
scene.constraint.gt(F2.y - F1.y, 0.05, description="the upper bar rests on top of the lower one")