# No. 408 (Brown 1868): "Centrolinead for drawing lines toward an inaccessible or inconveniently distant point; chiefly used in perspective. Upper
# or drawing edge of blade and back of movable legs should intersect center of joint. Geometrical diagram indicates mode of setting instrument, legs
# forming it may form unequal angles with blade. At either end of dotted line crossing central, a pin is inserted vertically for instrument to work
# against. ..."
#
# Model (cm, a plan: the instrument lies on the drawing, so no gravity). The legs are set (clamped) at 60 deg to the blade's drawing edge
# produced, their backs and the drawing edge meeting at the joint's centre. Two pins stand on the circle through the distant point, 18 cm to
# the left on the drawing edge produced; the legs' backs bear on the pins (real contact). The hand presses the instrument towards the pins (a light
# spring, 40 N/m) and turns it 15 deg either way: the one driven joint is the instrument's turning; it is otherwise free on the paper (two
# slides), so the pins alone guide it. The legs keep their angles to the pins, so the joint runs round the circle and the drawing edge always points
# at the distant point (Euclid III.21). A light readout pivoted at the distant point and pinned at the instrument records the bearing of the
# instrument from it; it carries nothing. Generator: opencode-runs/batch13/gen408.py.
number: 408
slug: centrolinead
name: Centrolinead
brown: "Centrolinead for drawing lines toward an inaccessible or inconveniently distant point; chiefly used in perspective. Upper or drawing edge of blade and back of movable legs should intersect center of joint. Geometrical diagram indicates mode of setting instrument, legs forming it may form unequal angles with blade. At either end of dotted line crossing central, a pin is inserted vertically for instrument to work against. Supposing it to be inconvenient to produce the convergent lines until they intersect, even temporarily, for the purpose of setting the instrument as shown, a corresponding convergence may be found between them by drawing a line parallel to and inward from each."
units: cm
sim: {timestep: 0.0001, integrator: implicitfast, iterations: 60, duration_s: 10, floor: false, gravity: 0}
bodies:
  - id: paper
    shape: part
    pos: [0, 0, 0]
    fixed: true
    friction: 0.05
    color: "#efe8d8"
    pieces:
      - {kind: poly, points: [[-0.04, 0.0], [-0.0677, 0.7061], [0.0123, 0.7061], [0.04, 0.0]], y: [0.55, 0.6], color: "#8f8a80"}   # the circle through the pins and the distant point (Brown's diagram), dotted
      - {kind: poly, points: [[-0.1503, 1.4017], [-0.2882, 2.0948], [-0.2092, 2.1073], [-0.0713, 1.4142]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-0.4785, 2.7688], [-0.7231, 3.4318], [-0.647, 3.4565], [-0.4024, 2.7935]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-1.0166, 4.0678], [-1.3619, 4.6843], [-1.2906, 4.7206], [-0.9453, 4.1041]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-1.7512, 5.2666], [-2.1887, 5.8215], [-2.124, 5.8685], [-1.6865, 5.3136]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-2.6643, 6.3357], [-3.1833, 6.8154], [-3.1267, 6.8719], [-2.6078, 6.3922]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-3.7334, 7.2488], [-4.321, 7.6414], [-4.274, 7.7061], [-3.6864, 7.3135]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-4.9322, 7.9834], [-5.574, 8.2793], [-5.5377, 8.3506], [-4.8959, 8.0547]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-6.2312, 8.5215], [-6.9114, 8.7133], [-6.8866, 8.7894], [-6.2065, 8.5976]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-7.5983, 8.8497], [-8.3001, 8.9327], [-8.2876, 9.0118], [-7.5858, 8.9287]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-9.0, 8.96], [-9.7061, 8.9323], [-9.7061, 9.0123], [-9.0, 9.04]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-10.4017, 8.8497], [-11.0948, 8.7118], [-11.1073, 8.7908], [-10.4142, 8.9287]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-11.7688, 8.5215], [-12.4318, 8.2769], [-12.4565, 8.353], [-11.7935, 8.5976]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-13.0678, 7.9834], [-13.6843, 7.6381], [-13.7206, 7.7094], [-13.1041, 8.0547]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-14.2666, 7.2488], [-14.8215, 6.8113], [-14.8685, 6.876], [-14.3136, 7.3135]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-15.3357, 6.3357], [-15.8154, 5.8167], [-15.8719, 5.8733], [-15.3922, 6.3922]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-16.2488, 5.2666], [-16.6414, 4.679], [-16.7061, 4.726], [-16.3135, 5.3136]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-16.9834, 4.0678], [-17.2793, 3.426], [-17.3506, 3.4623], [-17.0547, 4.1041]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-17.5215, 2.7688], [-17.7133, 2.0886], [-17.7894, 2.1134], [-17.5976, 2.7935]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-17.8497, 1.4017], [-17.9327, 0.6999], [-18.0118, 0.7124], [-17.9287, 1.4142]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-17.96, 0.0], [-17.9323, -0.7061], [-18.0123, -0.7061], [-18.04, 0.0]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-17.8497, -1.4017], [-17.7118, -2.0948], [-17.7908, -2.1073], [-17.9287, -1.4142]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-17.5215, -2.7688], [-17.2769, -3.4318], [-17.353, -3.4565], [-17.5976, -2.7935]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-16.9834, -4.0678], [-16.6381, -4.6843], [-16.7094, -4.7206], [-17.0547, -4.1041]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-16.2488, -5.2666], [-15.8113, -5.8215], [-15.876, -5.8685], [-16.3135, -5.3136]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-15.3357, -6.3357], [-14.8167, -6.8154], [-14.8733, -6.8719], [-15.3922, -6.3922]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-14.2666, -7.2488], [-13.679, -7.6414], [-13.726, -7.7061], [-14.3136, -7.3135]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-13.0678, -7.9834], [-12.426, -8.2793], [-12.4623, -8.3506], [-13.1041, -8.0547]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-11.7688, -8.5215], [-11.0886, -8.7133], [-11.1134, -8.7894], [-11.7935, -8.5976]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-10.4017, -8.8497], [-9.6999, -8.9327], [-9.7124, -9.0118], [-10.4142, -8.9287]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-9.0, -8.96], [-8.2939, -8.9323], [-8.2939, -9.0123], [-9.0, -9.04]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-7.5983, -8.8497], [-6.9052, -8.7118], [-6.8927, -8.7908], [-7.5858, -8.9287]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-6.2312, -8.5215], [-5.5682, -8.2769], [-5.5435, -8.353], [-6.2065, -8.5976]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-4.9322, -7.9834], [-4.3157, -7.6381], [-4.2794, -7.7094], [-4.8959, -8.0547]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-3.7334, -7.2488], [-3.1785, -6.8113], [-3.1315, -6.876], [-3.6864, -7.3135]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-2.6643, -6.3357], [-2.1846, -5.8167], [-2.1281, -5.8733], [-2.6078, -6.3922]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-1.7512, -5.2666], [-1.3586, -4.679], [-1.2939, -4.726], [-1.6865, -5.3136]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-1.0166, -4.0678], [-0.7207, -3.426], [-0.6494, -3.4623], [-0.9453, -4.1041]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-0.4785, -2.7688], [-0.2867, -2.0886], [-0.2106, -2.1134], [-0.4024, -2.7935]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[-0.1503, -1.4017], [-0.0673, -0.6999], [0.0118, -0.7124], [-0.0713, -1.4142]], y: [0.55, 0.6], color: "#8f8a80"}
      - {kind: poly, points: [[14.7619, -5.239], [28.4619, -7.4088], [28.4619, -7.3088], [14.7619, -5.139]], y: [0.55, 0.6], color: "#3a3632"}   # lines already drawn towards the distant point
      - {kind: poly, points: [[14.7619, -2.6284], [28.4619, -3.7066], [28.4619, -3.6066], [14.7619, -2.5284]], y: [0.55, 0.6], color: "#3a3632"}
      - {kind: poly, points: [[14.7619, 2.5284], [28.4619, 3.6066], [28.4619, 3.7066], [14.7619, 2.6284]], y: [0.55, 0.6], color: "#3a3632"}
      - {kind: poly, points: [[14.7619, 5.139], [28.4619, 7.3088], [28.4619, 7.4088], [14.7619, 5.239]], y: [0.55, 0.6], color: "#3a3632"}
      - {kind: disc, center: [-18.0, 0], radius: 0.25, y: [0.5, 0.6], color: "#3a3632"}   # the distant point
  - id: pin_a
    shape: part
    pos: [-4.5, 0, 7.7942]
    fixed: true
    friction: 0.05
    color: "#5c5244"
    pieces:
      - {kind: disc, center: [-4.5, 7.7942], radius: 0.4, y: [-1.2, 0.55], collide: 1}   # a pin, upright in the board
  - id: pin_b
    shape: part
    pos: [-4.5, 0, -7.7942]
    fixed: true
    friction: 0.05
    color: "#5c5244"
    pieces:
      - {kind: disc, center: [-4.5, -7.7942], radius: 0.4, y: [-1.2, 0.55], collide: 1}   # the other pin
  - {id: car_x, shape: part, pos: [0, 0, 0], mass: 0.002, pieces: [{kind: rod, from: [0, -3, 0], to: [0, -2.95, 0], radius: 0.05}]}
  - {id: car_z, shape: part, pos: [0, 0, 0], mount: car_x, mass: 0.002, pieces: [{kind: rod, from: [0, -3, 0], to: [0, -2.95, 0], radius: 0.05}]}
  - id: inst
    shape: part
    pos: [0, 0, 0]
    mount: car_z
    density: 1400
    friction: 0.05
    color: "#d8ccb0"
    pieces:
      - {kind: poly, points: [[-0.5781, 1.8013], [-7.5381, 13.8564], [-6.4989, 14.4564], [0.4611, 2.4013]], y: [-0.4, 0.4], collide: 2}   # the upper leg, its back bearing on a pin
      - {kind: poly, points: [[-0.5781, -1.8013], [-7.5381, -13.8564], [-6.4989, -14.4564], [0.4611, -2.4013]], y: [-0.4, 0.4], collide: 2}   # the lower leg
      - {kind: poly, points: [[2.5419, -1.4], [26.4619, -1.4], [26.4619, 0.0], [2.5419, 0.0]], y: [-0.4, 0.4]}   # the blade, its upper edge the drawing edge
      - {kind: disc, center: [0.4619, 0], radius: 2.6, y: [-0.5, 0.45], color: "#b8a888"}   # the joint's round plate
      - {kind: disc, center: [-0.3381, 1.3856], radius: 0.45, y: [-0.75, -0.5], color: "#8f8a80"}   # a leg's clamping screw
      - {kind: disc, center: [-0.3381, -1.3856], radius: 0.45, y: [-0.75, -0.5], color: "#8f8a80"}   # the other's
      - {kind: disc, center: [3.6619, -0.7], radius: 0.4, y: [-0.75, -0.4], color: "#8f8a80"}   # the blade's screw
      - {kind: disc, center: [0.4619, 0], radius: 0.15, y: [-0.65, -0.5], color: "#3a3632"}   # the joint's centre
  - {id: rd_arm, shape: part, pos: [-18.0, 0, 0], mass: 0.002, pieces: [{kind: rod, from: [-18.0, -3, 0], to: [-18.0, -2.95, 0], radius: 0.05}]}
  - {id: rd_rad, shape: part, pos: [0, 0, 0], mount: rd_arm, mass: 0.002, pieces: [{kind: rod, from: [0, -3, 0], to: [0, -2.95, 0], radius: 0.05}]}
pins:
  - {id: p_read, a: rd_rad, b: inst, at: [0, 0, 0]}   # the readout at the instrument (where the legs' backs, set off by a pin's radius, meet)
joints:
  - {id: j_x, type: slide, body: car_x, axis: [1, 0, 0], stiffness: 40, springref: -3, damping: 2}   # the hand pressing the instrument towards the pins (and steadying it)
  - {id: j_z, type: slide, body: car_z, axis: [0, 0, 1], damping: 2}   # free across
  - {id: j_r, type: hinge, body: inst, axis: [0, 1, 0]}   # the one driven joint: the hand turning the instrument
  - {id: j_v, type: hinge, body: rd_arm, axis: [0, 1, 0]}   # readout: the instrument's bearing from the distant point
  - {id: j_d, type: slide, body: rd_rad, axis: [1, 0, 0]}   # readout: its distance from the distant point, less 18
contact: {solref: [0.002, 1], solimp: [0.95, 0.99, 0.0005], margin: 0}
driver: {joint: j_r, kind: velocity, rpm: 0, swing: {amplitude: 0.2618, hz: 0.3}, kv: 2, max_torque: 2}
checks:
  - {type: follow, out: j_v, in: j_r, expect: 1.0, tol: 0.02, min_r2: 0.999, settle_s: 1.0, window_s: 6}   # the drawing edge always points at the distant point: its bearing from it turns as the blade turns
  - {type: amplitude, joint: j_r, min: 0.1047, max: 0.3665, sustain: 0.7, settle_s: 1.0, window_s: 6}   # the hand turned the instrument well
  - {type: penetration, max: 0.004, settle_s: 0.5}
camera: {target: [2, 0, -6.6], position: [2, -80, -6.6], fov: 36}
display:
  output: j_v
  labels: {j_r: "The hand turning the instrument (driver)", j_x: "Instrument along", j_z: "Instrument across", j_v: "Bearing from the distant point", j_d: "Distance from the distant point"}
