Engineering Journal
Pdf Processor
Pdf Processor

Engineering Journal: The Math Behind Context-Aware PDF Extraction

2026-05-07

Entry 42: the blind extraction problem

Standard, linear PDF extraction pipelines, extracting vector segments, finding intersecting grids, and dumping text into bounding boxes, fail catastrophically on complex documents containing interleaved paragraphs, titles, and tables. Decorative underlines generate phantom 1x1 tables, while coordinate jitter causes text slightly outside cell borders to drop out of the extracted output entirely. A working engine must stop reading PDFs sequentially and begin classifying layout spatially.

Entry 43: KD-tree proximity & underline discrimination

To eliminate phantom tables, we introduced the contextClassifier. Before running table extraction passes, the classifier categorizes all document elements into typed spatial regions (TABLE, PARAGRAPH, HEADING, LIST, IMAGE).

To differentiate decorative underlines from table borders, we implemented baseline proximity math:

// Proximity check: Is the horizontal segment an underline?
export function isBaselineUnderline(hSegment, textMetaItems) {
  const hY = (hSegment.y1 + hSegment.y2) / 2;

for (const item of textMetaItems) { const yDist = hY - item.vy;

// Line sits 0 to 5px below text baseline with overlapping X span if (yDist >= -1 && yDist <= 5 && isXOverlap(item, hSegment)) { return true; } } return false; }

Filtering vector segments that meet this baseline proximity condition eliminated $99\%$ of hallucinated tables across our test corpus.


Entry 44: region scoping and nearest-cell snapping

To prevent table content from leaking into paragraph text, text items located inside table bounding boxes are assigned to the table region and marked as consumed in a central assignedTextIndices bitset:
const tableTextIndices = [];
textMetaItems.forEach(item => {
  if (isPointInsideBBox(item.vx, item.vy, tableBBox)) {
    tableTextIndices.push(item.idx);
    assignedTextIndices.add(item.idx); // Mark consumed
  }
});

To resolve coordinate jitter data loss, we replaced strict bounding-box checks with a nearest-neighbor Euclidean proximity model. Text items snap to the nearest table cell center within a $15\text{px}$ threshold, reducing extraction data loss to zero.


Entry 45: the page assembler pipeline

The pageAssembler receives classified, non-overlapping spatial regions, sorts them vertically by Y-coordinates, and invokes specialized block builders: The resulting pipeline produces clean, semantically correct HTML matching true document reading order without relying on server processing or probabilistic ML models.
Rule of thumb: Pre-classify spatial document regions and use baseline proximity math to filter decorative line noise before reconstructing tables.
Read this post in the full Engineering Journal →