{
  "schemaVersion": 1,
  "slug": "trapezoid-area-calculator",
  "category": "geometry",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "d63d6cdb6b975b8caf4f02305bdf8f9c5953f3495002cba3dce675f3dde2a10e",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/trapezoid-area-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "A = (a+b)h/2; m = (a+b)/2; P = a+b+c+d; x = ±√(c²−h²); D₁ = √((x+a)²+h²); D₂ = √((b−x)²+h²)",
    "vars": [
      [
        "a,b",
        "Parallel top and bottom bases"
      ],
      [
        "h",
        "Perpendicular height"
      ],
      [
        "c,d",
        "Left and right legs"
      ],
      [
        "x",
        "Signed horizontal projection of the left leg, chosen to fit the right leg"
      ],
      [
        "A,m,P",
        "Area, midline and perimeter"
      ],
      [
        "D₁,D₂",
        "Diagonals"
      ]
    ],
    "note": "Legs shorter than the perpendicular height or incompatible with the bases are rejected. The horizontal projection may have either sign; no invalid leg is repaired by clipping. Use one consistent length unit; area uses its square."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-18",
    "sources": [
      {
        "name": "OpenStax — Geometric formulas",
        "url": "https://openstax.org/books/prealgebra/pages/c-geometric-formulas"
      }
    ],
    "basis": "Area is the average of the parallel bases multiplied by perpendicular height; the midline is that average. Perimeter is the sum of both bases and both legs. With bases 6 and 12, height 4 and legs 5 and 5, area is 36 square units, midline 9 and perimeter 28. The left leg gives a horizontal projection of either sign; the calculator chooses a sign consistent with the right leg and uses Pythagoras for both diagonals. Leg compatibility allows a difference of 0.01 length units or one hundred-millionth of the larger calculated/entered right leg, whichever is larger. This is an input-fit tolerance, not a measurement uncertainty estimate. Every input must be greater than zero and at most 100000; a leg cannot be shorter than the height.",
    "limitations": "Enter both parallel bases, the perpendicular height and both legs in the same length unit. All five measurements must describe one trapezoid. The calculator checks the legs before returning area, midline, perimeter and diagonals; it also accepts equal bases when the legs fit.",
    "implementationHash": "d63d6cdb6b975b8caf4f02305bdf8f9c5953f3495002cba3dce675f3dde2a10e",
    "domain": "math"
  },
  "contract": {
    "compute": "const a=topBase, b=bottomBase, h=height, c=leftLeg, d=rightLeg;\nconst invalid={area:null,median:null,perimeter:null,diagonal1:null,diagonal2:null,__error:'inputError'};\nif (![a,b,h,c,d].every(v=>Number.isFinite(v)&&v>0&&v<=100000) || c<h || d<h) return invalid;\nconst xMagnitude=Math.sqrt(Math.max(0,c*c-h*h));\nconst expectedRight=x=>Math.sqrt((b-a-x)*(b-a-x)+h*h);\nconst tolerance=x=>Math.max(0.01,1e-8*Math.max(d,expectedRight(x)));\nlet x;\nif(Math.abs(expectedRight(xMagnitude)-d)<=tolerance(xMagnitude)) x=xMagnitude;\nelse if(Math.abs(expectedRight(-xMagnitude)-d)<=tolerance(-xMagnitude)) x=-xMagnitude;\nelse return invalid;\nconst area=(a+b)/2*h, median=(a+b)/2;\nconst diagonal1=Math.sqrt((x+a)*(x+a)+h*h), diagonal2=Math.sqrt((b-x)*(b-x)+h*h);\nreturn {area,median,perimeter:a+b+c+d,diagonal1,diagonal2};",
    "inputs": [
      {
        "name": "topBase",
        "type": "number",
        "default": 6,
        "min": 0,
        "max": 100000,
        "step": 0.01,
        "requiredValue": true,
        "strictRange": true
      },
      {
        "name": "bottomBase",
        "type": "number",
        "default": 12,
        "min": 0,
        "max": 100000,
        "step": 0.01,
        "requiredValue": true,
        "strictRange": true
      },
      {
        "name": "height",
        "type": "number",
        "default": 4,
        "min": 0,
        "max": 100000,
        "step": 0.01,
        "requiredValue": true,
        "strictRange": true
      },
      {
        "name": "leftLeg",
        "type": "number",
        "default": 5,
        "min": 0,
        "max": 100000,
        "step": 0.01,
        "requiredValue": true,
        "strictRange": true
      },
      {
        "name": "rightLeg",
        "type": "number",
        "default": 5,
        "min": 0,
        "max": 100000,
        "step": 0.01,
        "requiredValue": true,
        "strictRange": true
      }
    ],
    "outputs": [
      {
        "name": "area",
        "precision": 3,
        "unit": "unit²",
        "notation": "auto"
      },
      {
        "name": "median",
        "precision": 3,
        "unit": "unit",
        "notation": "auto"
      },
      {
        "name": "perimeter",
        "precision": 3,
        "unit": "unit",
        "notation": "auto"
      },
      {
        "name": "diagonal1",
        "precision": 4,
        "unit": "unit",
        "notation": "auto"
      },
      {
        "name": "diagonal2",
        "precision": 4,
        "unit": "unit",
        "notation": "auto"
      }
    ],
    "interpret": null
  }
}
