{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "drilling-derrick",
  "type": "registry:component",
  "title": "Platform drilling derrick",
  "description": "Modular platform drilling rig on skid beams: braced substructure, drill floor with rotary table, mousehole, bell nipple and flowline, and a four-leg lattice derrick with K and X bracing, an inverted-V V-door, a racking board with fingers and racked stands, and a crown block with gin pole and aviation lights. It also carries the drawworks with its drill line, top-drive guide rails, a travelling block and top drive positioned by `topDrive`, a standpipe and rotary hose, the driller's cabin, and a V-door pipe ramp down to the catwalk.",
  "dependencies": [
    "three",
    "@react-three/fiber",
    "@react-three/drei"
  ],
  "registryDependencies": [
    "https://deck-twin-library.demoareeb.workers.dev/r/core.json"
  ],
  "files": [
    {
      "path": "wellhead/drilling-derrick.tsx",
      "type": "registry:file",
      "target": "components/deck-twin/wellhead/drilling-derrick.tsx",
      "content": "// Platform drilling rig: substructure and drill floor, lattice derrick with V-door, racking board, crown block, travelling block + top drive, drawworks, doghouse, pipe ramp. API 4F / API 8C.\nimport * as THREE from 'three'\nimport type { Kit, V3 } from '../lib/kit'\nimport { paint } from '../lib/materials'\nimport { KitMesh, useKit, type GroupProps } from '../lib/mesh'\nimport { checkerPlate, grating, handrail, ladder, member, tagPlate } from '../lib/parts'\nimport { textMaterial } from '../lib/textures'\n\nexport interface DrillingDerrickProps {\n  /** derrick height above the drill floor, m */\n  height?: number\n  /** square drill floor side, m */\n  floorSize?: number\n  /** drill floor above the deck (substructure height), m */\n  floorHeight?: number\n  /** top-drive gearbox height above the drill floor, m */\n  topDrive?: number\n  /** stands racked in the setback */\n  stands?: number\n  tag?: string\n}\n\nexport const defaults = { height: 43, floorSize: 13, floorHeight: 8, topDrive: 15, stands: 24, tag: 'DR-100' }\n\ntype P = typeof defaults\n\nconst WHITE = paint('#e4e2da', { metalness: 0.2, roughness: 0.55 })\nconst NAV = paint('#ff2a1a', { emissive: '#ff2a1a', emissiveIntensity: 1.6, roughness: 0.3 })\n\nfunction dims(p: P) {\n  const H = Math.max(20, p.height)\n  const S = Math.max(8, p.floorSize)\n  const F = Math.max(3, p.floorHeight)\n  const b0 = Math.min(S * 0.35, 4.5)\n  const b1 = Math.max(0.9, b0 * 0.31)\n  const bays = Math.max(6, Math.round(H / 3.6))\n  const dw = (h: number) => b0 + ((b1 - b0) * h) / H\n  const leg = (sx: number, sz: number, h: number): V3 => [sx * dw(h), F + h, sz * dw(h)]\n  const td = THREE.MathUtils.clamp(p.topDrive, 3, H - 9)\n  return { H, S, F, b0, b1, bays, dw, leg, td, monkey: H * 0.63 }\n}\n\nexport function DrillingDerrick(props: DrillingDerrickProps & GroupProps) {\n  const { height, floorSize, floorHeight, topDrive, stands, tag, ...group } = { ...defaults, ...props }\n  const p = { height, floorSize, floorHeight, topDrive, stands, tag } as P\n  const D = dims(p)\n  const data = useKit((k) => build(k, p), [height, floorSize, floorHeight, stands, tag])\n  const hose = useKit((k) => buildHose(k, p), [height, floorSize, floorHeight, topDrive])\n  const block = useKit((k) => buildTravelling(k), [])\n  const falls = useKit((k) => buildFalls(k), [])\n  const crownY = D.F + D.H + 1.0\n  const yTD = D.F + D.td\n  const drop = crownY - (yTD + 5.5)\n  return (\n    <group {...group}>\n      <KitMesh data={data} />\n      <KitMesh data={hose} />\n      <group position={[0, yTD, 0]}>\n        <KitMesh data={block} />\n      </group>\n      <group position={[0, crownY, 0]} scale={[1, drop, 1]}>\n        <KitMesh data={falls} shadows={false} />\n      </group>\n    </group>\n  )\n}\n\nexport default DrillingDerrick\n\n/** Travelling block, hook, bails, top drive (frame, motor, gearbox, gooseneck), guide dolly. Origin: gearbox bottom on the well axis. */\nfunction buildTravelling(k: Kit) {\n  const yB = 5.0\n  k.cyl('actuatorYellow', 0.58, 1.3, [0, yB, 0], 'z', 28)\n  for (const s of [-1, 1]) k.box('actuatorYellow', [1.24, 1.5, 0.1], [0, yB - 0.14, s * 0.7])\n  k.cyl('nut', 0.1, 1.6, [0, yB, 0], 'z', 12)\n  k.box('actuatorYellow', [0.7, 0.65, 0.6], [0, yB - 0.95, 0])\n  k.torus('nut', 0.22, 0.06, [0, yB - 1.45, 0], 'z', 8, 20, Math.PI)\n  for (const s of [-1, 1]) k.rod('nut', [s * 0.25, yB - 1.3, 0], [s * 0.35, 2.3, 0], 0.045, 8)\n  k.rbox(WHITE, [1.2, 1.8, 1.1], 0.05, [0, 1.45, 0])\n  k.cyl('motorPaint', 0.36, 1.7, [0.15, 1.85, 0.85], 'y', 20)\n  k.cyl('motorPaint', 0.24, 0.15, [0.15, 2.78, 0.85], 'y', 16)\n  k.box('nut', [1.0, 0.55, 1.0], [0, 0.275, 0])\n  k.tube('nut', [[0.3, 2.35, -0.2], [0.3, 3.1, -0.2], [0.3, 3.3, -0.7]], 0.09, 10, 0.25)\n  for (const s of [-1, 1]) k.rod('nut', [s * 0.35, 0.2, 0], [s * 0.22, -2.4, 0], 0.05, 8)\n  k.box('actuatorYellow', [0.7, 0.3, 0.5], [0, -2.5, 0])\n  // quill, IBOPs, saver sub\n  k.cyl('nut', 0.11, 0.6, [0, -0.3, 0], 'y', 12)\n  for (const y of [-0.36, -0.16]) k.cyl('nut', 0.14, 0.12, [0, y, 0], 'y', 12)\n  k.box('actuatorYellow', [0.1, 0.36, 0.08], [0.17, -0.26, 0])\n  // guide dolly on the rails (-X)\n  k.box('nut', [0.6, 1.8, 0.9], [-0.9, 1.3, 0])\n  // stand in the elevator, down to the rotary\n  k.cyl('nut', 0.064, 3.0, [0, -2.0, 0], 'y', 10)\n}\n\n/** 8 drill-line falls from the crown (y = 0) to the block (y = -1); the group scales them by the drop. */\nfunction buildFalls(k: Kit) {\n  for (let i = 0; i < 8; i++) {\n    const z = -0.63 + i * 0.18\n    const s = i % 2 ? 1 : -1\n    k.rod('cable', [s * 0.78, 0, z], [s * 0.5, -1, z], 0.022, 5)\n  }\n}\n\nfunction build(k: Kit, p: P) {\n  const D = dims(p)\n  const { H, S, F, bays, dw, leg } = D\n  const h2 = S / 2\n\n  // ---------------------------------------------------------------- substructure\n  for (const s of [-1, 1]) {\n    member(k, [-h2 - 0.6, 0.45, s * (h2 - 0.6)], [h2 + 1.2, 0.45, s * (h2 - 0.6)], 'HEB 900', 'structSteelDark')\n    for (const x of [-h2 - 0.7, h2 + 1.3]) k.box('actuatorYellow', [0.3, 0.35, 1.0], [x, 1.07, s * (h2 - 0.6)])\n  }\n  const xs = [-h2 + 0.2, -h2 / 3, h2 / 3, h2 - 0.2]\n  const zs = [-h2 + 0.2, -h2 + 1.6, h2 - 1.6, h2 - 0.2]\n  const yb = 0.9\n  const yt = F - 0.9\n  const ym = (yb + yt) / 2\n  for (const x of xs) for (const z of zs) member(k, [x, yb, z], [x, yt, z], 'HEB 360', 'structSteel')\n  for (const z of zs) {\n    member(k, [xs[0], ym, z], [xs[3], ym, z], 'HEB 260', 'structSteel')\n    member(k, [-h2, F - 0.48, z], [h2, F - 0.48, z], 'HEB 800', 'structSteel')\n  }\n  for (const z of [zs[0], zs[3]])\n    for (let i = 0; i < xs.length - 1; i++)\n      for (const [y0, y1] of [[yb, ym], [ym, yt]]) {\n        member(k, [xs[i], y0, z], [xs[i + 1], y1, z], 'CHS 168.3x8', 'structSteel')\n        member(k, [xs[i + 1], y0, z], [xs[i], y1, z], 'CHS 168.3x8', 'structSteel')\n      }\n  for (const x of [xs[0], xs[3]])\n    for (const [z0, z1] of [[zs[0], zs[1]], [zs[2], zs[3]]]) {\n      member(k, [x, yb, z0], [x, yt, z1], 'CHS 168.3x8', 'structSteel')\n      member(k, [x, yb, z1], [x, yt, z0], 'CHS 168.3x8', 'structSteel')\n    }\n  for (const x of [-h2 + 0.2, -1.3, 1.3, h2 - 0.2]) member(k, [x, F - 0.42, -h2], [x, F - 0.42, h2], 'HEB 700', 'structSteel', [0, 1, 0])\n  // drill floor plate, rotary table, mousehole\n  checkerPlate(k, [0, F, 0], S, S, 0.06)\n  k.cyl('nut', 1.0, 0.5, [0, F + 0.2, 0], 'y', 40)\n  k.cyl('machined', 0.75, 0.04, [0, F + 0.47, 0], 'y', 40)\n  k.cyl('pipeBore', 0.32, 0.05, [0, F + 0.47, 0], 'y', 24)\n  for (const s of [-1, 1]) k.box('actuatorYellow', [0.5, 0.06, 0.25], [s * 0.45, F + 0.5, 0])\n  k.cyl('nut', 0.25, 0.08, [1.8, F + 0.04, 1.2], 'y', 20)\n  k.cyl('pipeBore', 0.2, 0.09, [1.8, F + 0.04, 1.2], 'y', 20)\n  // guard rail with openings at the V-door (+X) and the doghouse (+Z)\n  const e = 0.05\n  handrail(k, [[-h2 + e, F, -h2 + e], [h2 - e, F, -h2 + e], [h2 - e, F, -1.0]])\n  handrail(k, [[h2 - e, F, 1.0], [h2 - e, F, h2 - e], [2.5, F, h2 - e]])\n  handrail(k, [[-2.5, F, h2 - e], [-h2 + e, F, h2 - e], [-h2 + e, F, h2 - 2.5]])\n  handrail(k, [[-h2 + e, F, h2 - 3.5], [-h2 + e, F, -h2 + e]])\n  ladder(k, [-h2 - 0.4, 0, h2 - 3.0], F, [-1, 0, 0])\n  // bell nipple and riser under the rotary, flowline to the shakers\n  k.cyl('actuatorRed', 0.62, 1.2, [0, F - 1.8, 0], 'y', 28)\n  k.pipe('pipePaint', [0, 0, 0], [0, F - 2.4, 0], 0.55, 0.02, 28)\n  k.pipe('pipePaint', [0, F - 1.2, 0], [0, F - 0.1, 0], 0.68, 0.015, 28)\n  k.tube('pipePaint', [[-0.3, F - 1.0, 0], [-1.2, F - 1.05, 0], [-h2 - 1.0, F - 2.2, 0.5]], 0.15, 12, 0.6)\n\n  // ---------------------------------------------------------------- derrick\n  const C: [number, number][] = [[-1, -1], [1, -1], [1, 1], [-1, 1]]\n  const NRM: V3[] = [[0, 0, -1], [1, 0, 0], [0, 0, 1], [-1, 0, 0]]\n  const dh = H / bays\n  const vB = 3 // V-door bays on +X\n  for (const [sx, sz] of C) {\n    member(k, leg(sx, sz, 0), leg(sx, sz, H), 'SHS 400x400x16', WHITE)\n    const q = leg(sx, sz, 0)\n    k.box('structSteelDark', [1.0, 0.3, 1.0], [q[0], F + 0.15, q[2]])\n    k.box(WHITE, [0.5, 0.9, 0.03], [q[0] - sx * 0.42, F + 0.75, q[2]])\n    k.box(WHITE, [0.03, 0.9, 0.5], [q[0], F + 0.75, q[2] - sz * 0.42])\n  }\n  const mid = (a: V3, b: V3): V3 => [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2]\n  for (let i = 0; i <= bays; i++) {\n    const h0 = i * dh\n    for (let f = 0; f < 4; f++) {\n      const [ax, az] = C[f]\n      const [bx, bz] = C[(f + 1) % 4]\n      const vdoor = f === 1 && i < vB\n      if (i > 0 && !vdoor) member(k, leg(ax, az, h0), leg(bx, bz, h0), 'UPN 200', WHITE, NRM[f])\n      if (i === bays || vdoor) continue\n      const A0 = leg(ax, az, h0)\n      const B0 = leg(bx, bz, h0)\n      const A1 = leg(ax, az, h0 + dh)\n      const B1 = leg(bx, bz, h0 + dh)\n      if (i < 4) {\n        const m = i % 2 === 0 ? mid(A1, B1) : mid(A0, B0)\n        member(k, i % 2 === 0 ? A0 : A1, m, 'L150x150x15', WHITE, NRM[f])\n        member(k, i % 2 === 0 ? B0 : B1, m, 'L150x150x15', WHITE, NRM[f])\n      } else {\n        member(k, A0, B1, 'L120x120x12', WHITE, NRM[f])\n        member(k, B0, A1, 'L120x120x12', WHITE, NRM[f])\n      }\n    }\n    if (i > 0 && i < bays && i % 3 === 0)\n      for (let f = 0; f < 4; f++) {\n        const pa = leg(C[f][0], C[f][1], h0)\n        const pb = leg(C[(f + 1) % 4][0], C[(f + 1) % 4][1], h0)\n        const pc = leg(C[(f + 3) % 4][0], C[(f + 3) % 4][1], h0)\n        member(k, [pa[0] + (pb[0] - pa[0]) * 0.35, pa[1], pa[2] + (pb[2] - pa[2]) * 0.35], [pa[0] + (pc[0] - pa[0]) * 0.35, pa[1], pa[2] + (pc[2] - pa[2]) * 0.35], 'SHS 100x100x6.3', WHITE)\n      }\n  }\n  // V-door inverted-V frame\n  const apex: V3 = [dw(vB * dh), F + vB * dh, 0]\n  member(k, leg(1, -1, 0), apex, 'SHS 250x250x12.5', WHITE)\n  member(k, leg(1, 1, 0), apex, 'SHS 250x250x12.5', WHITE)\n\n  // racking (monkey) board with fingers and the derrickman's platform outside +X\n  const yM = F + D.monkey\n  const w = dw(D.monkey)\n  member(k, [w, yM, -w], [w, yM, w], 'UPN 300', 'structSteel', [1, 0, 0])\n  for (const s of [-1, 1]) member(k, [0.8, yM, s * (w - 0.05)], [w, yM, s * (w - 0.05)], 'UPN 260', 'structSteel')\n  for (let j = 0; j < 6; j++) for (const s of [-1, 1]) member(k, [0.85, yM + 0.05, s * (0.56 + j * 0.3)], [w, yM + 0.05, s * (0.56 + j * 0.3)], 'SHS 100x100x6.3', 'actuatorYellow')\n  grating(k, [w + 0.6, yM - 0.12, 0], 1.2, 2.6)\n  handrail(k, [[w, yM - 0.12, -1.3], [w + 1.2, yM - 0.12, -1.3], [w + 1.2, yM - 0.12, 1.3], [w, yM - 0.12, 1.3]])\n  // racked stands in the setback, leaning into the fingers\n  const n = Math.max(0, Math.round(p.stands))\n  for (let j = 0; j < n; j++) {\n    const row = j % 2 ? 1 : -1\n    const c = Math.floor(j / 2)\n    const z = row * (0.4 + (c % 6) * 0.3 + 0.15)\n    const x0 = 1.6 + Math.floor(c / 6) * 0.25\n    k.rod('nut', [x0, F + 0.05, z * 0.9], [0.95 + Math.floor(c / 6) * 0.25, yM + 2.5, z], 0.064, 8)\n  }\n  k.box('rubberBlack', [1.2, 0.08, 4.0], [2.0, F + 0.04, 0])\n\n  // crown: water table, sheave cluster, gin pole, rails, aviation lights\n  const yc = F + H\n  const hw = dw(H)\n  k.box('structSteel', [2 * hw + 0.8, 0.6, 2 * hw + 0.8], [0, yc - 0.3, 0])\n  grating(k, [0, yc + 0.03, 0], 2 * hw + 1.4, 2 * hw + 1.4)\n  const r = hw + 0.65\n  handrail(k, [[-r, yc + 0.03, -r], [r, yc + 0.03, -r], [r, yc + 0.03, r], [-r, yc + 0.03, r], [-r, yc + 0.03, -r + 0.6]])\n  for (const s of [-1, 1]) k.box('structSteelDark', [2.2, 1.9, 0.16], [0, yc + 0.95, s * 0.95])\n  k.cyl('actuatorYellow', 0.8, 1.7, [0, yc + 1.0, 0], 'z', 32)\n  k.cyl('nut', 0.12, 1.9, [0, yc + 1.0, 0], 'z', 12)\n  k.cyl('actuatorYellow', 0.45, 0.3, [-1.4, yc + 1.2, 0.6], 'z', 20)\n  for (const s of [-1, 1]) member(k, [s * 1.5, yc + 0.03, 0], [0, yc + 4.6, 0], 'CHS 114.3x6.3', WHITE)\n  member(k, [0, yc + 4.6, -0.3], [0, yc + 4.6, 0.3], 'CHS 114.3x6.3', WHITE)\n  k.sphere(NAV, 0.22, [0, yc + 4.95, 0], undefined, 12)\n  for (const [sx, sz] of C) {\n    const q: V3 = [sx * (hw + 0.55), yc + 1.4, sz * (hw + 0.55)]\n    k.rod('structSteelDark', [q[0], yc + 0.03, q[2]], [q[0], q[1] - 0.15, q[2]], 0.04, 6)\n    k.sphere(NAV, 0.17, q, undefined, 10)\n    const m = leg(sx, sz, H / 2)\n    k.sphere(NAV, 0.16, [m[0] + sx * 0.3, m[1], m[2] + sz * 0.3], undefined, 10)\n  }\n  // derrick ladder with rest platforms up the -X,-Z leg\n  ladder(k, [-D.b0 - 0.6, F, -D.b0], F + H * 0.5, [-1, 0, 0], { cage: true })\n\n  // drill line: fast line to the drawworks drum, dead-line anchor\n  const xd = -h2 + 1.8\n  k.rod('cable', [-1.85, yc + 1.2, 0.6], [xd + 0.3, F + 1.75, 0.3], 0.028, 5)\n  k.rod('cable', [-0.78, yc + 1.0, -0.75], [-0.9, F + 0.75, -3.9], 0.028, 5)\n  k.box('structSteelDark', [0.7, 0.8, 0.7], [-0.9, F + 0.4, -3.9])\n  // top-drive guide rails on the -X side, tied back to the derrick\n  const xr = -1.3\n  for (const s of [-1, 1]) member(k, [xr, F + 3, s * 0.35], [xr, F + H - 4.5, s * 0.35], 'HEB 200', 'structSteelDark', [1, 0, 0])\n  for (let h = 6; h < H - 5; h += 7) member(k, [xr, F + h, 0], [-dw(h), F + h, 0], 'SHS 100x100x6.3', 'structSteelDark')\n\n  // drawworks: skid, drum with drill line wraps, AC motors, disc brakes, guard\n  k.box('structSteelDark', [2.0, 0.3, 3.4], [xd, F + 0.15, 0])\n  k.cyl('nut', 0.55, 2.0, [xd, F + 1.0, 0], 'z', 32)\n  for (let j = -6; j <= 6; j++) k.torus('cable', 0.57, 0.022, [xd, F + 1.0, j * 0.14], 'z', 5, 32)\n  for (const s of [-1, 1]) {\n    k.cyl('actuatorRed', 0.85, 0.08, [xd, F + 1.0, s * 1.08], 'z', 36)\n    k.box('nut', [0.3, 0.4, 0.2], [xd + 0.7, F + 1.3, s * 1.1])\n    k.cyl('motorPaint', 0.45, 1.0, [xd - 0.2, F + 0.75, s * 1.75], 'z', 24)\n  }\n  k.box('actuatorYellow', [1.6, 0.05, 2.0], [xd, F + 1.75, 0])\n  // standpipe up the -X,+Z leg with gooseneck, rotary hose to the top drive\n  const sp = (h: number): V3 => {\n    const q = leg(-1, 1, h)\n    return [q[0] + 0.35, q[1], q[2] - 0.35]\n  }\n  const hs = Math.min(14, H * 0.33)\n  k.tube('nut', [[sp(0)[0], 0.9, sp(0)[2] + 0.2], [sp(0)[0], F + 0.4, sp(0)[2]], sp(hs), [sp(hs)[0] + 0.45, sp(hs)[1] + 0.85, sp(hs)[2] - 0.45]], 0.075, 10, 0.4)\n  for (let h = 2; h < hs; h += 3) k.rod('structSteelDark', sp(h), leg(-1, 1, h), 0.04, 6)\n  // doghouse (driller's cabin) on the +Z edge with windows facing the rotary\n  const dx = -h2 + 2.2\n  const dz = h2 - 1.6\n  k.rbox('cladding', [4.0, 3.0, 2.8], 0.05, [dx, F + 1.5, dz])\n  for (const j of [-1, 0, 1]) k.box('glass', [1.1, 1.0, 0.02], [dx + j * 1.25, F + 1.9, dz - 1.41])\n  k.box('glass', [0.02, 0.9, 1.6], [dx + 2.01, F + 1.9, dz - 0.2])\n  k.box('structSteelDark', [0.9, 2.1, 0.03], [dx + 1.3, F + 1.05, dz + 1.41])\n  k.rbox('plasticGrey', [0.9, 0.6, 0.7], 0.04, [dx - 1.0, F + 3.3, dz])\n  k.box(textMaterial(\"DRILLER'S CABIN\", '#1f3e70', '#ffffff', 512, 96), [1.6, 0.3, 0.01], [dx, F + 2.75, dz - 1.41])\n  tagPlate(k, p.tag, [dx + 1.3, F + 2.3, dz + 1.42], 'z', 0.35)\n\n  // V-door pipe ramp down to the catwalk (+X)\n  const rampL = Math.hypot(F - 1.1, F * 1.25)\n  const ang = Math.atan2(F - 1.1, F * 1.25)\n  const rq = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), -ang)\n  k.box('safetyYellow', [rampL, 0.08, 1.2], [h2 + (F * 1.25) / 2, (F + 1.1) / 2, 0], rq)\n  for (const s of [-1, 1]) k.box('safetyYellow', [rampL, 0.25, 0.08], [h2 + (F * 1.25) / 2, (F + 1.1) / 2 + 0.12, s * 0.6], rq)\n  for (let i = 1; i < 4; i++) {\n    const x = h2 + (F * 1.25 * i) / 4\n    const y = F - ((F - 1.1) * i) / 4\n    member(k, [x, 0, 0], [x, y - 0.1, 0], 'HEB 200', 'structSteel')\n  }\n  const cx0 = h2 + F * 1.25\n  checkerPlate(k, [cx0 + 6, 1.1, 0], 12, 2.4)\n  for (let x = cx0; x <= cx0 + 12; x += 3) for (const s of [-1, 1]) member(k, [x, 0, s * 1.1], [x, 1.03, s * 1.1], 'HEB 200', 'structSteel')\n  for (const s of [-1, 1]) member(k, [cx0, 1.0, s * 1.15], [cx0 + 12, 1.0, s * 1.15], 'UPN 200', 'structSteel', [0, 0, 1])\n}\n\n/** Rotary hose from the standpipe gooseneck to the top-drive gooseneck, sagging between them. */\nfunction buildHose(k: Kit, p: P) {\n  const D = dims(p)\n  const { F, H, leg } = D\n  const sp = (h: number): V3 => {\n    const q = leg(-1, 1, h)\n    return [q[0] + 0.35, q[1], q[2] - 0.35]\n  }\n  const hs = Math.min(14, H * 0.33)\n  const g: V3 = [sp(hs)[0] + 0.7, sp(hs)[1] + 0.35, sp(hs)[2] - 0.7]\n  const tdG: V3 = [0.3, F + D.td + 3.3, -0.7]\n  const sag = Math.max(1, (g[1] + tdG[1]) / 2 - (F + 1.5))\n  k.spline('rubberBlack', [g, [(g[0] + tdG[0]) / 2, (g[1] + tdG[1]) / 2 - Math.min(sag, 4), (g[2] + tdG[2]) / 2], tdG], 0.07, 8, 30)\n\n}\n"
    }
  ],
  "categories": [
    "wellhead"
  ],
  "meta": {
    "export": "DrillingDerrick",
    "anchor": "base",
    "standards": [
      "API 4F",
      "API 8C",
      "API 7K",
      "ISO 18647",
      "ISO 14122"
    ]
  }
}